draftwright 0.4.7__tar.gz → 0.4.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- draftwright-0.4.9/.gitignore +28 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/CHANGELOG.md +162 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/PKG-INFO +8 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/README.md +6 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/docs/adr/README.md +5 -4
- {draftwright-0.4.7 → draftwright-0.4.9}/docs/reference/recogniser-capabilities.md +10 -3
- {draftwright-0.4.7 → draftwright-0.4.9}/pyproject.toml +4 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/skills/SKILL.md +15 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/_core.py +37 -12
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/_geometry.py +384 -42
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/_common.py +264 -44
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/balloons.py +83 -52
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/from_model.py +779 -112
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/holes.py +341 -15
- draftwright-0.4.9/src/draftwright/annotations/leaders.py +2243 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/orchestrator.py +135 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/sections.py +258 -58
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/builder.py +44 -4
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/compose.py +19 -5
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/drawing.py +364 -94
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/evaluation/step_analysis.py +227 -6
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/layout.py +96 -17
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/__init__.py +12 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/coverage.py +44 -2
- draftwright-0.4.9/src/draftwright/linting/evidence.py +423 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/hole_coverage.py +93 -19
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/issues.py +9 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/pmi_coverage.py +18 -1
- draftwright-0.4.9/src/draftwright/linting/quality.py +672 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/structural.py +246 -111
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/callout.py +26 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/compiled.py +157 -7
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/detect.py +26 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/planner.py +251 -28
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/projection.py +222 -28
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/recogniser_contract.py +103 -7
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/repair.py +7 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/sheet_emit.py +15 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/conftest.py +73 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/bracket_section.json +26 -20
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/grooved_shaft.json +14 -14
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/pocketed.json +14 -8
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/scattered_plate.json +42 -32
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/side_drilled.json +8 -8
- draftwright-0.4.9/tests/test_architecture_docs.py +25 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_audit_differential.py +11 -3
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_detect_registry.py +36 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_drawing_encapsulation.py +6 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_e2e_standards.py +4 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_flat_completeness.py +14 -8
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_flat_stock_identity.py +10 -16
- draftwright-0.4.9/tests/test_iso_nts_caption_placement.py +611 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1073_cross_body_patterns.py +19 -7
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1143_hole_completeness.py +40 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1144_transactional_hole_table.py +34 -11
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1146_scale_completeness.py +3 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1147_legibility_pair_aggregation.py +15 -2
- draftwright-0.4.9/tests/test_issue_1153_contradictory_dimensions.py +292 -0
- draftwright-0.4.9/tests/test_issue_1154_one_owner_per_measurement.py +584 -0
- draftwright-0.4.9/tests/test_issue_1166_cross_pass_feature_leaders.py +2356 -0
- draftwright-0.4.9/tests/test_issue_1176_quality_fidelity.py +988 -0
- draftwright-0.4.9/tests/test_issue_1177_angular_dimensions.py +518 -0
- draftwright-0.4.9/tests/test_issue_1187_unroutable_leaders.py +111 -0
- draftwright-0.4.9/tests/test_issue_1188_per_view_assignment.py +101 -0
- draftwright-0.4.9/tests/test_issue_1190_section_decision.py +253 -0
- draftwright-0.4.9/tests/test_issue_1196_deterministic_view_names.py +422 -0
- draftwright-0.4.9/tests/test_issue_1202_observed_drawing_consumer.py +625 -0
- draftwright-0.4.9/tests/test_issue_1204_multiscale_view_issues.py +335 -0
- draftwright-0.4.9/tests/test_issue_1215_envelope_tolerance.py +326 -0
- draftwright-0.4.9/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +913 -0
- draftwright-0.4.9/tests/test_issue_1216_callout_reservation_measures_ink.py +167 -0
- draftwright-0.4.9/tests/test_issue_1216_pairwise_across_scale_groups.py +125 -0
- draftwright-0.4.9/tests/test_issue_1217_claimed_representations.py +490 -0
- draftwright-0.4.9/tests/test_issue_1217_the_facility_is_shared.py +422 -0
- draftwright-0.4.9/tests/test_issue_1219_location_claims_its_own_axis.py +268 -0
- draftwright-0.4.9/tests/test_issue_1229_ledger_member_keying.py +177 -0
- draftwright-0.4.9/tests/test_issue_1240_iso_above_strip_visibility.py +405 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_676_polygonal_boss.py +11 -7
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_740_leader_assignment.py +139 -30
- draftwright-0.4.9/tests/test_issue_798_floor_cardinality.py +202 -0
- draftwright-0.4.9/tests/test_issue_798_material_field.py +495 -0
- draftwright-0.4.9/tests/test_issue_798_silhouette_lint.py +308 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_916_pocket_leader.py +5 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_917_open_channel.py +4 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_958_cross_solid_recognition.py +7 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_label_provenance.py +9 -4
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_layout_cleanliness.py +4 -7
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_layout_hypothesis.py +1 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_leader_footprint.py +10 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_lint_structural.py +20 -81
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_make_drawing.py +164 -83
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pmi.py +23 -4
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_private_test_attr_reads.py +5 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_private_test_imports.py +32 -2
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_quality_components.py +41 -1
- draftwright-0.4.9/tests/test_recogniser_adoption.py +43 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_recogniser_capabilities.py +138 -24
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_recognition.py +20 -4
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_recognition_manifest.py +135 -6
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_recognition_result.py +13 -136
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_render_seam.py +136 -17
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_emit.py +1 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_slanted_blind_step.py +8 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_slot_completeness.py +12 -6
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_strip_layout.py +19 -10
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_suppression_ledger.py +11 -1
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_tolerances.py +244 -18
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_two_repository_workflow.py +14 -3
- draftwright-0.4.7/.gitignore +0 -16
- draftwright-0.4.7/src/draftwright/linting/quality.py +0 -352
- draftwright-0.4.7/tests/test_architecture_docs.py +0 -43
- {draftwright-0.4.7 → draftwright-0.4.9}/LICENSE +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/docs/reference/sheet.md +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/_pmi_part21.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/_warnings.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/analysis.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotate.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/annotations/gears.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/audit.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/cli.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/evaluation/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/export.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fits.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/intents.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/channel_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/flat_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/gear_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/polygonal_stock_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/slot_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/make_drawing.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/declare.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/model/ir.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/pmi.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/py.typed +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/recognition/__init__.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/recognition_cache.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/registry.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/score.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/src/draftwright/sheet.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/_kernel.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/_layout_sig.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/README.md +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/blind-hole.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/corpus-v1.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/plain-block.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/topology-a.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/evaluation/topology-b.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/issue_915_case_study_2.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/grid_plate.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_add_dimension.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_agents_guide.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_api_docs.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_balloon_ring_standoff.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_compiled_plan_boundary.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_counting_calls.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_cross_repository_delivery_protocol.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_declare.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_declared_recognition_gate.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_deprecation_dates.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_detect_once.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_dimension_role_vocabulary.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_e2e_slice.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_export_dxf_curves.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_external_recognition_boundary.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_fits.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_flat_stock_opposition.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_gdt_placement.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_grid_lattice_convention.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_import_boundaries.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1000_envelope_reuse.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1058_wheel_profile.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1082_polygonal_stock.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1086_declared_gears.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_1142_hole_leader_labels.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_367_leader_ink.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_885_prismatic_coverage.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_909_sloped_profile.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_915_dense_case.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_issue_955_height_contingency.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_layout.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_layout_property.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_lint_reconciliation.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_linting.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_location_vocabulary.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_note_verb.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_object_aspects.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_parameter_id.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_part_model.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pitch_dim_footprint.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pmi_datum_lowering.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pmi_gtol_lowering.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pmi_part21.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pocket_pattern.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_pocket_pattern_recognition.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_principal_profile_classifier.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_recogniser_contract.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_refactor_golden.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_registry.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_repack_geometry_seam.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_score.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_script_detail_parity.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_shared_box_memo.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_gdt.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_identity_invariant.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_notes.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_of.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_section.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_sheet_tables.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_slot_pattern.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_soft_deprecation.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_solve_trace.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_step_analysis_evaluation.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_suppression_marks.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_turned_steps.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_witness_label_reconciliation.py +0 -0
- {draftwright-0.4.7 → draftwright-0.4.9}/tests/test_workflows.py +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
*.pyo
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
testenv/
|
|
10
|
+
.coverage
|
|
11
|
+
.coverage.*
|
|
12
|
+
coverage.xml
|
|
13
|
+
coverage*.json
|
|
14
|
+
htmlcov/
|
|
15
|
+
site/
|
|
16
|
+
.DS_Store
|
|
17
|
+
|
|
18
|
+
# Drawing exports. `Drawing.export()` writes wherever the calling script runs from, so
|
|
19
|
+
# ad-hoc scripts drop artefacts in the repo root — `bracket.pdf` and `grm01.pdf` were
|
|
20
|
+
# swept into a commit that way. These are build products, never sources.
|
|
21
|
+
#
|
|
22
|
+
# PDF and DXF have no tracked instances, so they are ignored anywhere. SVG and PNG DO
|
|
23
|
+
# (docs/images/), so only the repo root is ignored — the one place throwaway scripts
|
|
24
|
+
# write to — rather than hiding a legitimate new docs image.
|
|
25
|
+
*.pdf
|
|
26
|
+
*.dxf
|
|
27
|
+
/*.svg
|
|
28
|
+
/*.png
|
|
@@ -1,6 +1,167 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## v0.4.9 — 2026-08-21
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Lint now verifies that an annotation claiming to carry a measurement actually renders it
|
|
8
|
+
(#1217). Coverage checks read provenance riders the annotations carry about themselves and
|
|
9
|
+
believed them; nothing checked the claim against what the annotation draws. Four new codes —
|
|
10
|
+
`claimed_value_absent`, `claimed_measurement_not_compiled`, and two that report an
|
|
11
|
+
unverifiable claim rather than passing it — and `Drawing.add_table` now keeps the rows it
|
|
12
|
+
draws so a table's claims are readable back. Measured over all 21 STEP fixtures: 1,081
|
|
13
|
+
claims, 1,078 confirmed, and three findings — all instances of one genuine provenance
|
|
14
|
+
defect, see #1219.
|
|
15
|
+
|
|
16
|
+
- `lint_summary()["quality"]` gains a fourth component, `fidelity`: whether what the drawing
|
|
17
|
+
says is TRUE. The existing three ask whether required content landed (completeness),
|
|
18
|
+
whether there is too much of it (restraint), and whether a reader can make it out
|
|
19
|
+
(legibility) — none asked whether it is correct, so a drawing labelled 99 over a 16 mm
|
|
20
|
+
path reported a perfect score on every component available to it. Also covers a callout
|
|
21
|
+
drawn for a feature the part does not have, and a gear data table stating a tooth count
|
|
22
|
+
the geometry contradicts — the last of which reports `passed: True` and zero errors, so
|
|
23
|
+
the only existing channel that names it is `by_code`. Completeness, restraint and fidelity
|
|
24
|
+
report `available: False` with a `reason` rather than a flattering number when they have no
|
|
25
|
+
evidence, and every lint code the engine emits is classified onto exactly one component,
|
|
26
|
+
an explicit unscored register, or a register of codes whose component depends on the
|
|
27
|
+
issue's `outcome_stage`. `quality["unscored"]` reports the findings that reached no
|
|
28
|
+
component at all and flags any whose classification nobody made — `section_dropped` was
|
|
29
|
+
found scoring on nothing while a comment beside its emission said the opposite, and eleven
|
|
30
|
+
more `*_dropped` codes reach the engine as `drop_code` data with the same shape (#1176).
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.4 to 0.2.6.
|
|
35
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `aa52bc04216cd1eccc05796d2262547c7f476b80a3ec77334a77b9d8e3241a58` are
|
|
36
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
37
|
+
normal consumer gates run on the generated PR.
|
|
38
|
+
- `HoleRequirementOutcome` gains `members` and `features`, `ClaimOutcome` gains `measurement`,
|
|
39
|
+
and `linting.hole_coverage.canonical_hole_sites` is public (#1217). A consumer attributing a
|
|
40
|
+
requirement outcome to a specific recognised hole needs the evidence the outcome accounts
|
|
41
|
+
for, and needs to key into the canonical space the ledger publishes it in — a through hole's
|
|
42
|
+
own-axis coordinate is zeroed there.
|
|
43
|
+
- The STEP-analysis benchmark's `drawing_consumer` boundary now consumes
|
|
44
|
+
`hole_requirement_outcomes` instead of a second correspondence implementation of its own
|
|
45
|
+
(#1206), and follows the ledger's pointer through `linting.evidence` rather than trusting it.
|
|
46
|
+
Holes the ledger reports `unverifiable` now score `unknown` where the duplicate credited them
|
|
47
|
+
by guessing: 26 holes, five on each CTC-03 fixture and eight on each CTC-04 fixture. The
|
|
48
|
+
five-case evaluation corpus is unchanged, and one lint message on CTC-03 now reports its
|
|
49
|
+
coordinates in the ledger's own canonical space.
|
|
50
|
+
|
|
51
|
+
- `Drawing.suppressions()` rows gain a `conveyed_by` key: the dimension that states a
|
|
52
|
+
withheld measurement instead, or `None` when nothing takes the fact over (#1154). It is not
|
|
53
|
+
a synonym for the existing `authored` flag — that says whose decision it was, this says
|
|
54
|
+
where the measurement went.
|
|
55
|
+
|
|
56
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.2 to 0.2.4.
|
|
57
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `d0023d30e583c03abc55f09dfeaaa56fddf56334afa0417818480b2fa2ce3f0f` are
|
|
58
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
59
|
+
normal consumer gates run on the generated PR.
|
|
60
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.1 to 0.2.2.
|
|
61
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `7985befc8572bfe6d1c0805dfdf690d74a5a4a5f14d5988cc29c366315ff04ca` are
|
|
62
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
63
|
+
normal consumer gates run on the generated PR.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- An authored tolerance the compiler approved now reaches the sheet wherever the measurement
|
|
68
|
+
is drawn (#1215, #1216). `build123d_drafting` resolves a dimension's text as
|
|
69
|
+
`label if label is not None else _number_with_units(measured, tolerance)`, and every
|
|
70
|
+
dimension this engine emits passes a label — so a forwarded `tolerance=` rendered nothing
|
|
71
|
+
while type-checking and reading back correctly from `Dimension.label`. Ten render paths
|
|
72
|
+
discarded the band that way: envelope extents, the height ladder, the turned-step chain, two
|
|
73
|
+
public `Drawing` verbs, the deferred corridor route, the detail-view redraw, the short-rise
|
|
74
|
+
escape, step shoulders, pattern pitch, compound-callout recess terms, grid pitch, and both
|
|
75
|
+
hole tables. A general guard now decorates every parameter of every feature across a corpus,
|
|
76
|
+
through both `decorations=` key shapes, and joins what the compiler approved against what the
|
|
77
|
+
claiming annotation renders.
|
|
78
|
+
|
|
79
|
+
- Collapsed `N×` marks no longer state a tolerance their members do not share (#1216). A
|
|
80
|
+
pattern's pitch claimed the authored band of every gap although the recogniser admits 2%
|
|
81
|
+
jitter — holes at −30, −10, 10.3, 30 printed `3× 20 ±0.1` over a 20.3 mm gap — and fillet and
|
|
82
|
+
flat collapses took the "first-authored" band, so one of four fillets at ±0.1 printed
|
|
83
|
+
`4× R5 ±0.1`. Equality is now judged at the drawn precision, and a withheld band is reported
|
|
84
|
+
(`pattern_pitch_tolerance_withheld`, `collapsed_tolerance_withheld`) rather than dropped
|
|
85
|
+
silently.
|
|
86
|
+
|
|
87
|
+
- An approved dimension that cannot be placed is now reported instead of vanishing (#1216).
|
|
88
|
+
The overall extents' corridor candidate carried a no-op drop handler — the only drop in the
|
|
89
|
+
engine that recorded nothing — and the step ladder's legibility floor skipped rungs without
|
|
90
|
+
incrementing any counter. Both now record against the measurement they concern, and a
|
|
91
|
+
withholding is withdrawn if a later pass draws the measurement after all.
|
|
92
|
+
|
|
93
|
+
- A feature leader filling a view's below corridor no longer costs the part its overall extent
|
|
94
|
+
(#1236). The mandatory width or depth now retries on the view's above strip after every
|
|
95
|
+
corridor has drained, the fallthrough starved slot and plate dimensions already use. Live on
|
|
96
|
+
three NIST CTC fixtures, which drew no overall width.
|
|
97
|
+
|
|
98
|
+
- The iso view and the above strips are no longer invisible to each other (#1240). Strip
|
|
99
|
+
placement never saw the iso, and the iso fit re-scaled after annotation without consulting
|
|
100
|
+
what had been placed — so growth could invade dimension ink, which it did on CTC-01. The fit
|
|
101
|
+
is now capped by measured re-projection rather than by a linear model of it: the projected
|
|
102
|
+
bbox translates as it scales, by up to 7.35 mm on a part carrying a Location, which no
|
|
103
|
+
prediction about the page centre can express.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
- A part whose feature-local extent runs between the same two faces as an overall extent
|
|
107
|
+
is no longer dimensioned twice (#1154). GRM-04's drive plate printed `4.5` twice — once
|
|
108
|
+
as the hub's height and once as the overall thickness — because two detected records
|
|
109
|
+
claim one physical fact. The overall extent keeps it; the feature-local one is withheld
|
|
110
|
+
and records which dimension the reader finds it on. Reconciliation is by exact
|
|
111
|
+
support-plane coincidence, never by value: a square part's two equal extents run between
|
|
112
|
+
different faces and remain two facts (#997). A measurement is handed over only when the
|
|
113
|
+
extent receiving it is actually drawn — by the planner's rules, by the compiler's
|
|
114
|
+
overall-height rules, and by an authored set — and never when the yielding dimension
|
|
115
|
+
carries a tolerance, since a toleranced dimension and an untoleranced one are not the same
|
|
116
|
+
requirement. (A tolerance on the *receiving* extent is the same requirement on the same two
|
|
117
|
+
faces, and does not prevent the consolidation.)
|
|
118
|
+
|
|
119
|
+
## v0.4.8 — 2026-08-16
|
|
120
|
+
|
|
121
|
+
### Fixed
|
|
122
|
+
|
|
123
|
+
- Compatible automatic/deferred sparse ordinary side/plan hole and post-drain
|
|
124
|
+
machined-feature callouts now share one bounded same-view leader inventory
|
|
125
|
+
(#1166). Pattern, profiled-bore, and dense table-eligible hole queues retain
|
|
126
|
+
their specialised established paths because their winners affect downstream
|
|
127
|
+
furniture/table semantics or await #798 silhouette-aware routing. The solve
|
|
128
|
+
preserves required/priority-ranked evidence, rejects new-leader crossings,
|
|
129
|
+
checks complete leader ink against actual-width fixed dimension/witness,
|
|
130
|
+
arrow, label, and centre-furniture components (including rendered arrows on
|
|
131
|
+
shifted dimensions and component-local dashed circular centre furniture);
|
|
132
|
+
fixed residual faces and the selected survivor both require each tessellation
|
|
133
|
+
triangle to fit one same analytical component rather than merely the union,
|
|
134
|
+
plus exact continuous OCC containment for curved faces; residual lowering
|
|
135
|
+
also retains filled datum/GD&T faces absent from segment metadata; if candidate
|
|
136
|
+
or selected-survivor construction raises, or a survivor fails validation, the
|
|
137
|
+
bad alternative fails closed and the canonical lazy producer tail is replayed
|
|
138
|
+
instead of falsely dropping an otherwise valid callout; an all-invalid tail is
|
|
139
|
+
reported as validation-stage geometry failure rather than no clear room (so
|
|
140
|
+
scale fallback does not retry a non-spatial helper defect), while compiler
|
|
141
|
+
invariant violations such as a missing semantic callout label remain loud;
|
|
142
|
+
only explicitly marked global turning axes permit an arrow-local leader-tip
|
|
143
|
+
attachment; near-collinear shaft travel and ownerless section/cutting lines
|
|
144
|
+
remain fixed ink. The solve prefers
|
|
145
|
+
clear routes over explicit Policy-B fallbacks, and then minimises real leader
|
|
146
|
+
length. Provisional sections cannot veto that primary result: one separately
|
|
147
|
+
bounded refinement may choose an equally complete leader inventory that clears
|
|
148
|
+
their exact components, after which the final section performs one bounded
|
|
149
|
+
end-symbol repair and yields if exact ink still conflicts. The selected OCC survivor is validated against the same analytical
|
|
150
|
+
ink contract. A retained fixed-ink crossing now emits the machine-readable
|
|
151
|
+
`feature_leader_crossing` info finding instead of appearing lint-clean. Candidate,
|
|
152
|
+
fixed-component lowering, fixed-obstacle-probe, pair, and exact-search work is
|
|
153
|
+
bounded; the fixed inventory is lowered once and reused with the producer's
|
|
154
|
+
legacy lazy result as the floor, including state-cap exhaustion; page,
|
|
155
|
+
own-silhouette, and title-reservation constraints remain hard in every fallback.
|
|
156
|
+
A replay that exhausts exact fixed-probe classification is retained visibly as
|
|
157
|
+
`feature_leader_fixed_ink_unverified` rather than rescanning past the cap, and
|
|
158
|
+
that uncertainty participates in the legibility quality inventory.
|
|
159
|
+
Trace output preserves an abandoned fully admitted inventory when state search
|
|
160
|
+
exhausts, records the producer-floor replay separately, and names exact committed/provisional components,
|
|
161
|
+
refinement status, and competing blockers; live
|
|
162
|
+
single-callout edits remain immediate.
|
|
163
|
+
|
|
164
|
+
## v0.4.7 — 2026-08-16
|
|
4
165
|
|
|
5
166
|
### Added
|
|
6
167
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.9
|
|
4
4
|
Summary: Automated technical-drawing generation for build123d
|
|
5
5
|
Project-URL: Homepage, https://github.com/pzfreo/draftwright
|
|
6
6
|
Project-URL: Repository, https://github.com/pzfreo/draftwright
|
|
@@ -684,7 +684,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
684
684
|
Classifier: Topic :: Scientific/Engineering
|
|
685
685
|
Requires-Python: <3.15,>=3.10
|
|
686
686
|
Requires-Dist: antlr4-python3-runtime<4.10
|
|
687
|
-
Requires-Dist: b123d-recognisers==0.2.
|
|
687
|
+
Requires-Dist: b123d-recognisers==0.2.6
|
|
688
688
|
Requires-Dist: build123d-drafting-helpers>=0.14.1
|
|
689
689
|
Requires-Dist: build123d<0.11,>=0.9.0; python_full_version < '3.13'
|
|
690
690
|
Requires-Dist: build123d<0.12,>=0.11; python_full_version >= '3.13'
|
|
@@ -937,6 +937,12 @@ assert completeness["scope"] == "audited_recognized_requirements"
|
|
|
937
937
|
completeness["excludes"] # what the denominator cannot see
|
|
938
938
|
completeness["unrecognised_geometry_reports"] # a floor on that gap, never a measure
|
|
939
939
|
legibility = crit["quality"]["legibility"]
|
|
940
|
+
# `quality` also carries `fidelity` (#1176): is what the drawing says TRUE? A drawing can
|
|
941
|
+
# be complete, restrained and legible and still assert a measurement the part lacks.
|
|
942
|
+
fidelity = crit["quality"]["fidelity"]
|
|
943
|
+
# …and `unscored`, the findings no component priced, so four components reading "fine"
|
|
944
|
+
# cannot conceal that some of the critique was scored by nothing.
|
|
945
|
+
unscored = crit["quality"]["unscored"]
|
|
940
946
|
# Raw pair findings remain available and keep the original count semantics.
|
|
941
947
|
legibility["warnings"], legibility["by_code"], crit["issues"]
|
|
942
948
|
# The legibility scalar uses primary issues: one affected annotation/failure mechanism even
|
|
@@ -237,6 +237,12 @@ assert completeness["scope"] == "audited_recognized_requirements"
|
|
|
237
237
|
completeness["excludes"] # what the denominator cannot see
|
|
238
238
|
completeness["unrecognised_geometry_reports"] # a floor on that gap, never a measure
|
|
239
239
|
legibility = crit["quality"]["legibility"]
|
|
240
|
+
# `quality` also carries `fidelity` (#1176): is what the drawing says TRUE? A drawing can
|
|
241
|
+
# be complete, restrained and legible and still assert a measurement the part lacks.
|
|
242
|
+
fidelity = crit["quality"]["fidelity"]
|
|
243
|
+
# …and `unscored`, the findings no component priced, so four components reading "fine"
|
|
244
|
+
# cannot conceal that some of the critique was scored by nothing.
|
|
245
|
+
unscored = crit["quality"]["unscored"]
|
|
240
246
|
# Raw pair findings remain available and keep the original count semantics.
|
|
241
247
|
legibility["warnings"], legibility["by_code"], crit["issues"]
|
|
242
248
|
# The legibility scalar uses primary issues: one affected annotation/failure mechanism even
|
|
@@ -30,11 +30,12 @@ architecture** table; open retired or superseded records only for design history
|
|
|
30
30
|
| [0011](0011-ir-as-public-input.md) | The IR as a public input: declare features, don't only detect them | Accept the feature IR as public input through declarations and the `Sheet` façade. | Accepted; core landed; #62/#462/#495 remain | `test_declare.py`, `test_object_aspects.py`, `test_sheet_gdt.py` |
|
|
31
31
|
| [0012](0012-edits-as-pinned-priority-candidates-in-the-global-solve.md) | User annotation edits are pinned, priority-ranked corridor candidates | Drain recorded semantic edits through corridor placement with pin and priority. | Accepted; partially landed; full recomposition/parity remains #426/#707 (#661 detail views landed) | `test_make_drawing.py`, `test_sheet_emit.py` |
|
|
32
32
|
| [0013](0013-uniform-recognition-and-shared-package.md) | A uniform recogniser/feature contract and shared `b123d-recognisers` deployment | Enforce the geometry-only contract in the shared package and consume it through Draftwright's record→IR boundary. | Accepted; Phases 1–2 deployed | `test_external_recognition_boundary.py`, `test_detect_registry.py`, package semantic goldens |
|
|
33
|
-
| [0014](0014-collect-then-solve-annotation-placement.md) | Collect-then-solve annotation placement (as built) | Collect, select, assign, and deterministically solve annotations per corridor before rendering; post-drain
|
|
33
|
+
| [0014](0014-collect-then-solve-annotation-placement.md) | Collect-then-solve annotation placement (as built) | Collect, select, assign, and deterministically solve annotations per corridor before rendering; compatible sparse ordinary side/plan hole and post-drain machined leaders share one bounded late inventory. | Accepted; supersedes 0009; #740 Amendment 1; #1166 Amendment 2 | `test_carve_free_position_callers.py`, `test_strip_layout.py`, `test_layout_property.py`, `test_issue_740_leader_assignment.py`, `test_issue_1166_cross_pass_feature_leaders.py`, `test_import_boundaries.py` |
|
|
34
34
|
| [0015](0015-part-drawing-compiler-as-built.md) | The part-drawing compiler, as built | Use one detected-or-declared feature IR and planner-fed dimension groups as the compiler waist. | Accepted; supersedes 0008 | `test_part_model.py`, `test_detect_once.py`, `test_import_boundaries.py` |
|
|
35
|
-
| [0016](0016-declared-dimensioning-intent.md) | Declared dimensioning intent: capture what to measure, let the engine place it | Declare which measurements matter as scale-independent intent routed through the planner and corridor solve; never hardcode dimension geometry. | Accepted; epic #867 complete; phase 6 landed (#940) | `test_compiled_plan_boundary.py`, `test_label_provenance.py`, `test_sheet_emit.py`, `test_add_dimension.py` |
|
|
35
|
+
| [0016](0016-declared-dimensioning-intent.md) | Declared dimensioning intent: capture what to measure, let the engine place it | Declare which measurements matter as scale-independent intent routed through the planner and corridor solve; never hardcode dimension geometry. | Accepted; epic #867 complete; phase 6 landed (#940) | `test_compiled_plan_boundary.py`, `test_issue_1215_no_approved_tolerance_is_dropped.py`, `test_label_provenance.py`, `test_sheet_emit.py`, `test_add_dimension.py` |
|
|
36
36
|
| [0017](0017-recognition-inventory-correspondence-and-measurement-provenance.md) | One recognition result per run; correspondence is evidence-gated | Produce one external immutable recognition result held by Draftwright's per-run cache; require vertical-slice evidence before generalising correspondence, identity, requirements, outcomes, or reconciliation. | Accepted; external cache ownership clarified, extensions gated by #1018 | `test_external_recognition_boundary.py`, `test_recognition_manifest.py`, `test_declared_recognition_gate.py` |
|
|
37
|
-
| [0018](0018-requirement-driven-view-planning-and-editable-sheet-layout.md) | Requirement-driven view planning and editable sheet layout | Use one `ViewSpec` vocabulary and planner with distinct authored `ViewConstraints` and immutable `ResolvedViewPlan`; jointly validate views, typography, convention, scale, paper and layout against requirement survival.
|
|
37
|
+
| [0018](0018-requirement-driven-view-planning-and-editable-sheet-layout.md) | Requirement-driven view planning and editable sheet layout | Use one `ViewSpec` vocabulary and planner with distinct authored `ViewConstraints` and immutable `ResolvedViewPlan`; jointly validate views, typography, convention, scale, paper and layout against requirement survival. Supersedes ADR 0004's fixed-topology assumption while retaining compose-then-pack. | Accepted 2026-08-16 (nothing implemented yet); tracked by #1130 | Required guards are listed in the ADR |
|
|
38
|
+
| [0019](0019-display-complete-labels-and-dimension-outcomes.md) | Display-complete labels and a dimension-outcome ledger | The compiled plan carries the full label text (tolerance and collapse wording included) so renderers render and never compose; dimension outcomes reconcile at one seam on both build routes; ladder rungs get per-mark identity. Finishes the ADR 0016 Amdt 1 boundary; supersedes Amdt 6's enforcement mechanism. | Proposed | `test_issue_1215_no_approved_tolerance_is_dropped.py` reduces to plan-equality when implemented |
|
|
38
39
|
|
|
39
40
|
## Historical records
|
|
40
41
|
|
|
@@ -49,7 +50,7 @@ architecture** table; open retired or superseded records only for design history
|
|
|
49
50
|
- Compiler and state ownership: 0001 → 0005 → 0015.
|
|
50
51
|
- Recognition and public declaration: 0007 → 0013 → 0011 → 0015.
|
|
51
52
|
- Layout and placement: 0004 → 0014 → 0012 → 0018.
|
|
52
|
-
- Declared intent and the editable surface: 0001 → 0011 → 0012 → 0016 → 0018.
|
|
53
|
+
- Declared intent and the editable surface: 0001 → 0011 → 0012 → 0016 → 0018 → 0019.
|
|
53
54
|
- Quality and correction: 0002, with provenance from 0010.
|
|
54
55
|
- Recognition correspondence and completeness: 0007 → 0013 → 0015 → 0017.
|
|
55
56
|
|
|
@@ -15,9 +15,16 @@ library.
|
|
|
15
15
|
|
|
16
16
|
Validation fails closed and names the family and boundary whenever possible:
|
|
17
17
|
|
|
18
|
-
- **family inventory mismatch** —
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
- **family inventory mismatch (`stale=`)** — Draftwright declares a family the installed package
|
|
19
|
+
no longer ships, so a declared adapter would call a recogniser that is gone. Remove or repoint
|
|
20
|
+
the declaration.
|
|
21
|
+
|
|
22
|
+
The opposite direction does **not** fail this validation. A family the package ships and
|
|
23
|
+
Draftwright has not declared cannot reach any Draftwright code path, and blocking on it made the
|
|
24
|
+
package unreleasable until its consumer caught up. It is reported by
|
|
25
|
+
`pending_family_declarations` and fails `tests/test_recogniser_adoption.py` in Draftwright's own
|
|
26
|
+
CI instead — adoption is still required, and is enforced where the decision is made. Provide the
|
|
27
|
+
downstream behavior or an explicit non-supported state as before.
|
|
21
28
|
- **record schema mismatch** — a consumed record schema changed. Review the record fields and
|
|
22
29
|
compatibility notes, update the relevant adapter and tests, then pin the accepted schema version.
|
|
23
30
|
- **stale implementation** — a declared adapter, `Sheet` method, emitter, renderer, or completeness
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwright"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.9"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -18,7 +18,7 @@ dependencies = [
|
|
|
18
18
|
"build123d>=0.9.0,<0.11 ; python_full_version < '3.13'",
|
|
19
19
|
"build123d>=0.11,<0.12 ; python_full_version >= '3.13'",
|
|
20
20
|
"build123d-drafting-helpers>=0.14.1",
|
|
21
|
-
"b123d-recognisers==0.2.
|
|
21
|
+
"b123d-recognisers==0.2.6",
|
|
22
22
|
"numpy>=1.24",
|
|
23
23
|
# PNG raster export (SVG→PDF→PNG). Both permissively licensed (Pillow HPND; pypdfium2
|
|
24
24
|
# Apache-2.0 wrapping Google PDFium BSD-3) and ship pre-built wheels with NO native system
|
|
@@ -89,6 +89,7 @@ timeout = 300
|
|
|
89
89
|
markers = [
|
|
90
90
|
"slow: heavy end-to-end CTC fixture builds (deselected by default)",
|
|
91
91
|
"smoke: curated build-light subset for a fast local check (~30 s)",
|
|
92
|
+
"unit: pure-logic inner-loop tier — constructs NO OCC geometry (enforced by conftest, #656)",
|
|
92
93
|
]
|
|
93
94
|
# `SoftDeprecationWarning` marks a surface that is discouraged but SUPPORTED and not going
|
|
94
95
|
# away (#1043). The suite exercises `Sheet.auto_dimensions()` in ~170 places, deliberately —
|
|
@@ -164,6 +165,7 @@ dev = [
|
|
|
164
165
|
"mypy>=2.1.0",
|
|
165
166
|
"pytest>=8",
|
|
166
167
|
"pytest-cov>=5",
|
|
168
|
+
"pytest-split>=0.8",
|
|
167
169
|
"pytest-timeout>=2",
|
|
168
170
|
"pytest-xdist>=3",
|
|
169
171
|
"ruff>=0.4",
|
|
@@ -281,9 +281,22 @@ dwg = build_drawing(part)
|
|
|
281
281
|
|
|
282
282
|
# 1. Critique — the machine channel. JSON-friendly aggregate of lint().
|
|
283
283
|
crit = dwg.lint_summary()
|
|
284
|
-
# {"passed": bool, "score": 0..1, "
|
|
285
|
-
# "
|
|
284
|
+
# {"passed": bool, "score": 0..1, "diagnostic_score": 0..1,
|
|
285
|
+
# "errors": n, "warnings": n, "infos": n, "by_code": {code: n},
|
|
286
|
+
# "issues": [{code, severity, message, suggestion?}, ...],
|
|
287
|
+
# "quality": {"completeness": …, "restraint": …, "legibility": …, "fidelity": …,
|
|
288
|
+
# "unscored": {"available": True, "score": None, "issues": n,
|
|
289
|
+
# "by_code": {…}, "unclassified": [...], "reason": …}}}
|
|
286
290
|
# Gate on the severity/code COUNTS, not the scalar score.
|
|
291
|
+
#
|
|
292
|
+
# The four `quality` components answer four different questions and none substitutes for
|
|
293
|
+
# another: did required content land, is there too much of it, can a reader make it out,
|
|
294
|
+
# and — `fidelity` — is what it says TRUE. Completeness, restraint and fidelity report
|
|
295
|
+
# `available: False` with a `reason` rather than a flattering number when they have no
|
|
296
|
+
# evidence, so read `available` first. (Legibility is always available: an empty sheet
|
|
297
|
+
# genuinely IS legible, which is not the same kind of 1.0 as an empty sheet being truthful.)
|
|
298
|
+
# `quality["unscored"]` lists the findings none of the four priced; a non-empty
|
|
299
|
+
# `unclassified` there means a lint code reached no component and nobody decided it should.
|
|
287
300
|
|
|
288
301
|
# 2. Each issue names the problem in DOMAIN terms and (when computable) carries a
|
|
289
302
|
# ready-to-apply suggestion — a domain-API call you paste in, not page maths.
|
|
@@ -507,6 +507,36 @@ _MIN_STEP_SEP_MM = _FONT_SIZE + 2 * _PAD
|
|
|
507
507
|
_MIN_LOC_SEP_MM = draft_preset(font_size=_FONT_SIZE, decimal_precision=1).arrow_length + _PAD
|
|
508
508
|
|
|
509
509
|
|
|
510
|
+
def _classify_steps(step_zs, bb_min_z, scale, *, allow_short=False):
|
|
511
|
+
"""``(kept, too_close, too_short)`` — every step height, sorted into its outcome.
|
|
512
|
+
|
|
513
|
+
The one predicate. :func:`_legible_steps` is the historical two-value view of this and
|
|
514
|
+
delegates here, so the "which steps are dimensioned" rule cannot be stated twice and
|
|
515
|
+
drift; the third list exists because it was previously stated ZERO times.
|
|
516
|
+
|
|
517
|
+
``too_short`` is the silent case (#1216 review r9). A step whose page distance from the
|
|
518
|
+
part's base cannot carry a dimension is skipped, and unlike ``too_close`` the skip
|
|
519
|
+
incremented no counter, raised no escalation and produced no lint — so a blind hole in a
|
|
520
|
+
plate had its ``step_height`` approved by the compiler, dropped here, and the drawing
|
|
521
|
+
linted perfectly clean with the measurement nowhere on it. Callers report it; the guard in
|
|
522
|
+
``tests/test_issue_1215_no_approved_tolerance_is_dropped.py`` requires that they do.
|
|
523
|
+
"""
|
|
524
|
+
kept: list[float] = []
|
|
525
|
+
too_close: list[float] = []
|
|
526
|
+
too_short: list[float] = []
|
|
527
|
+
last = None
|
|
528
|
+
for z in sorted(step_zs):
|
|
529
|
+
if not allow_short and (z - bb_min_z) * scale < _MIN_STEP_DIM_MM:
|
|
530
|
+
too_short.append(z)
|
|
531
|
+
continue
|
|
532
|
+
if last is not None and (z - last) * scale < _MIN_STEP_SEP_MM:
|
|
533
|
+
too_close.append(z)
|
|
534
|
+
continue
|
|
535
|
+
kept.append(z)
|
|
536
|
+
last = z
|
|
537
|
+
return kept, too_close, too_short
|
|
538
|
+
|
|
539
|
+
|
|
510
540
|
def _legible_steps(step_zs, bb_min_z, scale, *, allow_short=False):
|
|
511
541
|
"""Step heights worth dimensioning at *scale*, and how many were too close.
|
|
512
542
|
|
|
@@ -518,19 +548,14 @@ def _legible_steps(step_zs, bb_min_z, scale, *, allow_short=False):
|
|
|
518
548
|
when they do not fit inline (#565). Returns ``(kept_zs, n_too_close)``:
|
|
519
549
|
the heights to dimension, and the count dropped for spacing (the caller
|
|
520
550
|
surfaces these via lint; the full-fidelity answer is a detail view, #42).
|
|
551
|
+
|
|
552
|
+
The steps dropped as too SHORT are not in either return value — see
|
|
553
|
+
:func:`_classify_steps`, which is where this rule now lives.
|
|
521
554
|
"""
|
|
522
|
-
kept
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
if not allow_short and (z - bb_min_z) * scale < _MIN_STEP_DIM_MM:
|
|
527
|
-
continue
|
|
528
|
-
if last is not None and (z - last) * scale < _MIN_STEP_SEP_MM:
|
|
529
|
-
n_too_close += 1
|
|
530
|
-
continue
|
|
531
|
-
kept.append(z)
|
|
532
|
-
last = z
|
|
533
|
-
return kept, n_too_close
|
|
555
|
+
kept, too_close, _too_short = _classify_steps(
|
|
556
|
+
step_zs, bb_min_z, scale, allow_short=allow_short
|
|
557
|
+
)
|
|
558
|
+
return kept, len(too_close)
|
|
534
559
|
|
|
535
560
|
|
|
536
561
|
def _legible_locations(positions, scale):
|