draftwright 0.4.19__tar.gz → 0.4.21__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.
Files changed (549) hide show
  1. {draftwright-0.4.19 → draftwright-0.4.21}/CHANGELOG.md +18 -1
  2. {draftwright-0.4.19 → draftwright-0.4.21}/PKG-INFO +4 -4
  3. {draftwright-0.4.19 → draftwright-0.4.21}/README.md +2 -2
  4. {draftwright-0.4.19 → draftwright-0.4.21}/docs/reference/recogniser-capabilities.md +102 -119
  5. {draftwright-0.4.19 → draftwright-0.4.21}/docs/reference/sheet.md +155 -0
  6. {draftwright-0.4.19 → draftwright-0.4.21}/pyproject.toml +7 -7
  7. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/_core.py +2 -4
  8. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/_geometry.py +72 -3
  9. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/analysis.py +13 -18
  10. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/_common.py +26 -3
  11. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/from_model.py +248 -59
  12. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/holes.py +34 -18
  13. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/orchestrator.py +11 -5
  14. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/audit.py +210 -69
  15. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/blend_contract.py +1 -1
  16. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/compose.py +14 -0
  17. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/drawing.py +166 -30
  18. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/evaluation/step_analysis.py +151 -82
  19. draftwright-0.4.21/src/draftwright/feature_identity.py +26 -0
  20. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/inspection.py +1 -1
  21. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/inspection_contract.py +5 -5
  22. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/__init__.py +4 -1
  23. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/blend_coverage.py +80 -1
  24. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/chamfer_coverage.py +1 -1
  25. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/channel_coverage.py +24 -8
  26. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/circular_blind_step_coverage.py +1 -1
  27. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/coverage.py +106 -119
  28. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/evidence.py +2 -6
  29. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/fillet_coverage.py +1 -1
  30. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/flat_coverage.py +1 -1
  31. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/groove_coverage.py +1 -1
  32. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/hole_coverage.py +164 -10
  33. draftwright-0.4.21/src/draftwright/linting/oriented_slot_coverage.py +299 -0
  34. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/pad_coverage.py +1 -1
  35. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/paired_ramp_step_coverage.py +1 -1
  36. draftwright-0.4.21/src/draftwright/linting/passage_coverage.py +16 -0
  37. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/plate_coverage.py +2 -2
  38. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/pocket_coverage.py +48 -10
  39. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/pocket_pattern_coverage.py +90 -34
  40. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/polygonal_boss_coverage.py +1 -1
  41. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/polygonal_stock_coverage.py +1 -1
  42. draftwright-0.4.21/src/draftwright/linting/prismatic_pocket_coverage.py +16 -0
  43. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/profiled_bore_coverage.py +56 -9
  44. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/quality.py +18 -17
  45. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/rectangular_blind_slot_coverage.py +32 -14
  46. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/requirements.py +6 -0
  47. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/round_bottom_blind_slot_coverage.py +34 -16
  48. draftwright-0.4.21/src/draftwright/linting/section_recess_coverage.py +102 -0
  49. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/slot_coverage.py +1 -1
  50. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/structural.py +41 -28
  51. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/suggest.py +8 -0
  52. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/through_step_coverage.py +1 -1
  53. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/turned_step_coverage.py +1 -1
  54. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/__init__.py +6 -0
  55. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/compiled.py +122 -53
  56. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/declare.py +85 -11
  57. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/detect.py +198 -407
  58. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/ir.py +414 -9
  59. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/planner.py +268 -66
  60. draftwright-0.4.21/src/draftwright/oriented_slot_contract.py +350 -0
  61. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/pmi.py +1 -1
  62. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recogniser_contract.py +81 -225
  63. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recogniser_policy.py +1 -33
  64. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recogniser_schema.py +46 -36
  65. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recognition/__init__.py +3 -3
  66. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recognition_cache.py +3 -3
  67. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recognition_frame.py +49 -13
  68. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/recognition_ownership.py +68 -12
  69. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/repair.py +86 -39
  70. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/reporting.py +23 -5
  71. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/score.py +2 -2
  72. draftwright-0.4.21/src/draftwright/section_recess_contract.py +714 -0
  73. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/sheet.py +156 -4
  74. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/sheet_emit.py +102 -52
  75. {draftwright-0.4.19 → draftwright-0.4.21}/tests/_recogniser_public_contract.py +16 -2
  76. draftwright-0.4.21/tests/_section_recess_cases.py +47 -0
  77. {draftwright-0.4.19 → draftwright-0.4.21}/tests/conftest.py +2 -2
  78. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_add_dimension.py +19 -0
  79. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_adr0018_view_selection.py +13 -9
  80. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_audit_differential.py +2 -2
  81. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_compiled_plan_boundary.py +6 -1
  82. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_counting_calls.py +1 -1
  83. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_declare.py +41 -24
  84. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_declared_recognition_gate.py +3 -3
  85. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_detect_once.py +1 -1
  86. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_detect_registry.py +18 -7
  87. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_e2e_standards.py +33 -1
  88. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_external_recognition_boundary.py +10 -11
  89. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_fillets_adjacency.py +1 -1
  90. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_flat_completeness.py +1 -1
  91. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_flat_stock_identity.py +1 -1
  92. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_flat_stock_opposition.py +1 -1
  93. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_geometry_graph_spike.py +5 -5
  94. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_grid_lattice_convention.py +3 -3
  95. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_import_boundaries.py +51 -47
  96. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_inspection_contract.py +5 -5
  97. draftwright-0.4.21/tests/test_issue_1006_measurement_comparison.py +269 -0
  98. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1058_wheel_profile.py +24 -26
  99. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1073_cross_body_patterns.py +26 -28
  100. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1082_polygonal_stock.py +2 -2
  101. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1143_hole_completeness.py +68 -12
  102. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1146_scale_completeness.py +1 -1
  103. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1155_grm04_sheet_use.py +5 -1
  104. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1166_cross_pass_feature_leaders.py +24 -0
  105. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1176_quality_fidelity.py +4 -1
  106. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1202_observed_drawing_consumer.py +2 -2
  107. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1204_multiscale_view_issues.py +3 -3
  108. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1229_ledger_member_keying.py +3 -3
  109. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1245_passage_disposition.py +31 -49
  110. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1246_prismatic_pocket_disposition.py +43 -28
  111. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1247_angled_step_disposition.py +2 -2
  112. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1254_turned_chamfers.py +1 -1
  113. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1262_automatic_turned_views.py +2 -1
  114. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1281_turned_fillets.py +1 -1
  115. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1308_machined_leader_analytics.py +34 -4
  116. draftwright-0.4.21/tests/test_issue_1333_bounded_ink_repair.py +287 -0
  117. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1351_structured_note_coverage.py +1 -1
  118. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1352_searchable_pdf_text.py +5 -5
  119. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1357_framed_activation.py +15 -4
  120. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1357_framed_boundary.py +2 -2
  121. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1357_plural_turned_profiles.py +7 -8
  122. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1357_pmi_frame.py +1 -1
  123. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1369_hole_completeness_evidence.py +2 -2
  124. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1370_countersink_completeness_evidence.py +5 -5
  125. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1370_double_d_completeness_evidence.py +10 -10
  126. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1370_hole_pattern_completeness_evidence.py +1 -1
  127. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1371_flat_completeness_evidence.py +1 -1
  128. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1371_polygonal_stock_completeness_evidence.py +13 -13
  129. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1372_groove_completeness_evidence.py +10 -7
  130. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1372_pad_completeness_evidence.py +1 -1
  131. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1372_pocket_completeness_evidence.py +56 -11
  132. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1372_pocket_pattern_completeness_evidence.py +74 -35
  133. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1372_polygonal_boss_completeness_evidence.py +2 -2
  134. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1373_plate_completeness_evidence.py +6 -6
  135. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1374_chamfer_completeness_evidence.py +3 -3
  136. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1374_fillet_completeness_evidence.py +3 -3
  137. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1374_turned_step_completeness_evidence.py +24 -16
  138. draftwright-0.4.21/tests/test_issue_1378_diameter_leader_targets.py +205 -0
  139. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1382_046_step_inventory.py +1 -1
  140. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1382_circular_blind_step_semantics.py +3 -3
  141. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1382_framed_step_family_evidence.py +3 -1
  142. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1382_paired_ramp_semantics.py +1 -1
  143. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1382_through_step_semantics.py +55 -31
  144. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1392_recognisers_048.py +8 -8
  145. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1397_unverifiable_requirement_message.py +12 -5
  146. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1421_rectangular_blind_slot_completeness.py +41 -32
  147. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1421_rectangular_blind_slot_semantics.py +67 -61
  148. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1421_round_bottom_blind_slot_completeness.py +41 -32
  149. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1421_round_bottom_blind_slot_semantics.py +67 -61
  150. draftwright-0.4.21/tests/test_issue_1432_adoption.py +257 -0
  151. draftwright-0.4.21/tests/test_issue_1432_boundary_failures.py +168 -0
  152. draftwright-0.4.21/tests/test_issue_1432_oriented_slot_semantics.py +1249 -0
  153. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1433_blend_semantics.py +20 -11
  154. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_boss_ownership.py +1 -1
  155. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_channel_ownership.py +34 -20
  156. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_generation_snapshot.py +1 -1
  157. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_nested_ownership.py +1 -1
  158. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_occurrence_ownership.py +12 -6
  159. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_pattern_ownership.py +4 -4
  160. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_plate_ownership.py +1 -1
  161. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_policy_dispositions.py +26 -16
  162. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_report_projection.py +50 -8
  163. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_through_step_ownership.py +5 -3
  164. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_turned_step_ownership.py +1 -1
  165. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1450_boss_blend_ownership.py +1 -1
  166. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1460_step_inspection.py +5 -3
  167. draftwright-0.4.21/tests/test_issue_1466_dimension_options.py +308 -0
  168. draftwright-0.4.21/tests/test_issue_1466_semantic_sides.py +317 -0
  169. draftwright-0.4.21/tests/test_issue_1471_boundary_failures.py +231 -0
  170. draftwright-0.4.21/tests/test_issue_1471_evidence_schema.py +37 -0
  171. draftwright-0.4.21/tests/test_issue_1471_groove_profile.py +179 -0
  172. draftwright-0.4.21/tests/test_issue_1471_section_recess_contract.py +259 -0
  173. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1471_section_recess_pockets.py +40 -30
  174. draftwright-0.4.21/tests/test_issue_1479_radius_leader_targets.py +262 -0
  175. draftwright-0.4.21/tests/test_issue_1485_curved_pockets.py +320 -0
  176. draftwright-0.4.21/tests/test_issue_1485_quiddity_024_boundary.py +71 -0
  177. draftwright-0.4.21/tests/test_issue_1485_rounded_pockets.py +286 -0
  178. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_676_polygonal_boss.py +2 -2
  179. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_740_leader_assignment.py +1 -0
  180. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_798_silhouette_lint.py +30 -8
  181. draftwright-0.4.21/tests/test_issue_827_real_part_canary.py +143 -0
  182. draftwright-0.4.21/tests/test_issue_883_location_identity.py +575 -0
  183. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_885_prismatic_coverage.py +2 -2
  184. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_909_sloped_profile.py +1 -1
  185. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_915_dense_case.py +24 -5
  186. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_916_pocket_leader.py +4 -28
  187. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_917_open_channel.py +68 -26
  188. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_958_cross_solid_recognition.py +32 -17
  189. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_make_drawing.py +83 -63
  190. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_parameter_id.py +28 -0
  191. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pitch_dim_footprint.py +10 -3
  192. draftwright-0.4.21/tests/test_pocket_pattern_recognition.py +206 -0
  193. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_quality_components.py +42 -29
  194. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_recogniser_adoption.py +2 -2
  195. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_recogniser_capabilities.py +230 -429
  196. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_recogniser_contract.py +46 -47
  197. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_recognition.py +29 -29
  198. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_recognition_result.py +6 -7
  199. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_score.py +6 -4
  200. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_emit.py +48 -11
  201. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_identity_invariant.py +1 -0
  202. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_slanted_blind_step.py +8 -8
  203. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_slot_completeness.py +1 -1
  204. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_slot_pattern_recognition.py +2 -2
  205. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_strip_layout.py +5 -0
  206. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_suppression_ledger.py +4 -1
  207. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_tolerances.py +11 -18
  208. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_turned_steps.py +1 -1
  209. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_workflows.py +40 -0
  210. draftwright-0.4.19/src/draftwright/linting/passage_coverage.py +0 -38
  211. draftwright-0.4.19/src/draftwright/linting/prismatic_pocket_coverage.py +0 -38
  212. draftwright-0.4.19/tests/test_pocket_pattern_recognition.py +0 -223
  213. {draftwright-0.4.19 → draftwright-0.4.21}/.gitignore +0 -0
  214. {draftwright-0.4.19 → draftwright-0.4.21}/LICENSE +0 -0
  215. {draftwright-0.4.19 → draftwright-0.4.21}/docs/adr/README.md +0 -0
  216. {draftwright-0.4.19 → draftwright-0.4.21}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
  217. {draftwright-0.4.19 → draftwright-0.4.21}/skills/SKILL.md +0 -0
  218. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/__init__.py +0 -0
  219. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/_build_profile.py +0 -0
  220. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/_pmi_part21.py +0 -0
  221. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/_warnings.py +0 -0
  222. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotate.py +0 -0
  223. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/__init__.py +0 -0
  224. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/balloons.py +0 -0
  225. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/gears.py +0 -0
  226. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/leaders.py +0 -0
  227. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/annotations/sections.py +0 -0
  228. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/builder.py +0 -0
  229. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/cli.py +0 -0
  230. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/evaluation/__init__.py +0 -0
  231. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/export.py +0 -0
  232. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fits.py +0 -0
  233. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
  234. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
  235. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
  236. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
  237. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/fonts/__init__.py +0 -0
  238. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/intents.py +0 -0
  239. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/layout.py +0 -0
  240. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/_registry.py +0 -0
  241. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/angled_step_coverage.py +0 -0
  242. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/gear_coverage.py +0 -0
  243. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/ink_overlap.py +0 -0
  244. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/issues.py +0 -0
  245. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/linting/pmi_coverage.py +0 -0
  246. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/make_drawing.py +0 -0
  247. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/callout.py +0 -0
  248. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/model/pmi_lowering.py +0 -0
  249. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/plate_correspondence.py +0 -0
  250. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/projection.py +0 -0
  251. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/py.typed +0 -0
  252. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/registry.py +0 -0
  253. {draftwright-0.4.19 → draftwright-0.4.21}/src/draftwright/view_plan.py +0 -0
  254. {draftwright-0.4.19 → draftwright-0.4.21}/tests/_kernel.py +0 -0
  255. {draftwright-0.4.19 → draftwright-0.4.21}/tests/_layout_sig.py +0 -0
  256. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/ap242_single_cylinder_diameter.step +0 -0
  257. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/README.md +0 -0
  258. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
  259. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/blind-hole.step +0 -0
  260. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-asymmetric.step +0 -0
  261. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-compound.step +0 -0
  262. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-overlap.step +0 -0
  263. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-plain.step +0 -0
  264. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-planar-x.step +0 -0
  265. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-planar-y.step +0 -0
  266. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-planar-z.step +0 -0
  267. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-topology-a.step +0 -0
  268. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-topology-b.step +0 -0
  269. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/chamfer-turned.step +0 -0
  270. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-chamfers-v1.json +0 -0
  271. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-countersinks-v1.json +0 -0
  272. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-double-d-bores-v1.json +0 -0
  273. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-fillets-v1.json +0 -0
  274. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-flats-v1.json +0 -0
  275. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-grooves-v1.json +0 -0
  276. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-hole-patterns-v1.json +0 -0
  277. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-plates-v1.json +0 -0
  278. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-pocket-patterns-v1.json +0 -0
  279. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-pockets-v1.json +0 -0
  280. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-polygonal-bosses-v1.json +0 -0
  281. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-polygonal-stock-v1.json +0 -0
  282. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-rectangular-pads-v1.json +0 -0
  283. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-turned-steps-v1.json +0 -0
  284. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/corpus-v1.json +0 -0
  285. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-deburr.step +0 -0
  286. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-external-cone.step +0 -0
  287. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-mixed-pair.step +0 -0
  288. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-single.step +0 -0
  289. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-topology-a.step +0 -0
  290. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/countersink-topology-b.step +0 -0
  291. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-axis-x.step +0 -0
  292. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-axis-y.step +0 -0
  293. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-blind.step +0 -0
  294. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-coaxial-compound.step +0 -0
  295. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-opposed-blind.step +0 -0
  296. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-roll-30.step +0 -0
  297. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-round-bore.step +0 -0
  298. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-single-z.step +0 -0
  299. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-topology-a.step +0 -0
  300. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/double-d-topology-b.step +0 -0
  301. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-compound.step +0 -0
  302. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-overlap.step +0 -0
  303. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-plain.step +0 -0
  304. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-planar-x.step +0 -0
  305. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-planar-y.step +0 -0
  306. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-planar-z.step +0 -0
  307. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-repeated.step +0 -0
  308. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-topology-a.step +0 -0
  309. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-topology-b.step +0 -0
  310. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/fillet-turned.step +0 -0
  311. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-coaxial.step +0 -0
  312. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-double-d.step +0 -0
  313. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-lone-d.step +0 -0
  314. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-nonround.step +0 -0
  315. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-slanted-double-d.step +0 -0
  316. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-topology-a.step +0 -0
  317. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/flat-topology-b.step +0 -0
  318. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-compound.step +0 -0
  319. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-lone-x.step +0 -0
  320. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-lone-y.step +0 -0
  321. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-lone-z.step +0 -0
  322. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-monotonic-negative.step +0 -0
  323. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-narrow.step +0 -0
  324. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-topology-a.step +0 -0
  325. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/groove-topology-b.step +0 -0
  326. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-compound-equal.step +0 -0
  327. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-detached-body-negative.step +0 -0
  328. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-full-span-ledge-negative.step +0 -0
  329. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-nested-staircase-negative.step +0 -0
  330. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-topology-a.step +0 -0
  331. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-topology-b.step +0 -0
  332. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-x-negative.step +0 -0
  333. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-x-positive.step +0 -0
  334. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-y-negative.step +0 -0
  335. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-y-positive.step +0 -0
  336. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-z-negative.step +0 -0
  337. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pad-z-positive.step +0 -0
  338. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pattern-ambiguous.step +0 -0
  339. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pattern-grid.step +0 -0
  340. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pattern-topology-a.step +0 -0
  341. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pattern-topology-b.step +0 -0
  342. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plain-block.step +0 -0
  343. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-compound-equal.step +0 -0
  344. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-cross-topology-a.step +0 -0
  345. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-cross-topology-b.step +0 -0
  346. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-detached-negative.step +0 -0
  347. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-rotational-negative.step +0 -0
  348. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-single-negative.step +0 -0
  349. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-t-xz.step +0 -0
  350. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-t-yz.step +0 -0
  351. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-thick-negative.step +0 -0
  352. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-u-additive.step +0 -0
  353. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/plate-u-cut.step +0 -0
  354. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-compound.step +0 -0
  355. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-edge-anchored.step +0 -0
  356. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-lone.step +0 -0
  357. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-opposed.step +0 -0
  358. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-ambiguous.step +0 -0
  359. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-grid.step +0 -0
  360. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-linear.step +0 -0
  361. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-pair.step +0 -0
  362. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-topology-a.step +0 -0
  363. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-pattern-topology-b.step +0 -0
  364. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-prismatic-negative.step +0 -0
  365. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-side.step +0 -0
  366. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-through-negative.step +0 -0
  367. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-topology-a.step +0 -0
  368. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-topology-b.step +0 -0
  369. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/pocket-two-equal.step +0 -0
  370. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-compound-equal.step +0 -0
  371. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-detached-negative.step +0 -0
  372. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-in-plane-rotated.step +0 -0
  373. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-other-protrusions-negative.step +0 -0
  374. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-recess-negative.step +0 -0
  375. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-stock-negative.step +0 -0
  376. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-topology-a.step +0 -0
  377. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-topology-b.step +0 -0
  378. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-x.step +0 -0
  379. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-y.step +0 -0
  380. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-boss-z.step +0 -0
  381. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-compound-negative.step +0 -0
  382. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-cylinder-negative.step +0 -0
  383. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-irregular-negative.step +0 -0
  384. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-octagon-negative.step +0 -0
  385. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-recess-negative.step +0 -0
  386. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-roll17.step +0 -0
  387. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-topology-a.step +0 -0
  388. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-topology-b.step +0 -0
  389. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-translated.step +0 -0
  390. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-x.step +0 -0
  391. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/polygonal-stock-y.step +0 -0
  392. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/topology-a.step +0 -0
  393. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/topology-b.step +0 -0
  394. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-axis-x.step +0 -0
  395. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-axis-y.step +0 -0
  396. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-axis-z.step +0 -0
  397. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-compound.step +0 -0
  398. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-repeated-lengths.step +0 -0
  399. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-through-bore.step +0 -0
  400. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-topology-a.step +0 -0
  401. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-topology-b.step +0 -0
  402. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/evaluation/turned-step-translated-blind-bore.step +0 -0
  403. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
  404. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/grm03_thumbwheel_drive_screw_ap242_pmi.step +0 -0
  405. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/grm04_drive_plate.step +0 -0
  406. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
  407. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
  408. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/issue_1247_angled_blind_step.step +0 -0
  409. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
  410. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/issue_915_case_study_2.step +0 -0
  411. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
  412. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
  413. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
  414. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
  415. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
  416. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
  417. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
  418. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
  419. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
  420. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
  421. {draftwright-0.4.19 → draftwright-0.4.21}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
  422. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/bracket_section.json +0 -0
  423. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/centered_rebate.json +0 -0
  424. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/chamfered.json +0 -0
  425. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/filleted.json +0 -0
  426. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/flange_dense.json +0 -0
  427. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/grid_plate.json +0 -0
  428. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/grooved_shaft.json +0 -0
  429. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/hex_bar.json +0 -0
  430. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/holed_slot.json +0 -0
  431. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/pocketed.json +0 -0
  432. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/prismatic_ladder.json +0 -0
  433. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/scattered_plate.json +0 -0
  434. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/side_drilled.json +0 -0
  435. {draftwright-0.4.19 → draftwright-0.4.21}/tests/refactor_golden/turned_stepped.json +0 -0
  436. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_adr0018_arrangement_gate.py +0 -0
  437. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_adr0018_view_routing.py +0 -0
  438. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_adr_corpus.py +0 -0
  439. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_agents_guide.py +0 -0
  440. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_api_docs.py +0 -0
  441. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_architecture_docs.py +0 -0
  442. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_balloon_ring_standoff.py +0 -0
  443. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_build_profile_harness.py +0 -0
  444. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_carve_free_position_callers.py +0 -0
  445. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_dense_sheet_canary.py +0 -0
  446. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_deprecation_dates.py +0 -0
  447. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_dimension_role_vocabulary.py +0 -0
  448. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_drawing_encapsulation.py +0 -0
  449. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_e2e_slice.py +0 -0
  450. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_export_dxf_curves.py +0 -0
  451. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_export_dxf_zoom.py +0 -0
  452. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_export_reproducible.py +0 -0
  453. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_fits.py +0 -0
  454. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_gdt_placement.py +0 -0
  455. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_iso_nts_caption_placement.py +0 -0
  456. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1000_envelope_reuse.py +0 -0
  457. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1086_declared_gears.py +0 -0
  458. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -0
  459. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1130_view_planning_evidence.py +0 -0
  460. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1142_hole_leader_labels.py +0 -0
  461. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1144_transactional_hole_table.py +0 -0
  462. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
  463. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
  464. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
  465. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1177_angular_dimensions.py +0 -0
  466. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1187_unroutable_leaders.py +0 -0
  467. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1188_per_view_assignment.py +0 -0
  468. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1190_section_decision.py +0 -0
  469. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1196_deterministic_view_names.py +0 -0
  470. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1209_linear_pmi_witnesses.py +0 -0
  471. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1215_envelope_tolerance.py +0 -0
  472. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +0 -0
  473. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1216_callout_reservation_measures_ink.py +0 -0
  474. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
  475. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1217_claimed_representations.py +0 -0
  476. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1217_the_facility_is_shared.py +0 -0
  477. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1219_location_claims_its_own_axis.py +0 -0
  478. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
  479. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1260_view_constraints.py +0 -0
  480. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1276_turned_leader_targets.py +0 -0
  481. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1296_cylindrical_diameter_pmi.py +0 -0
  482. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1298_manufacturing_requirements.py +0 -0
  483. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1299_page_escalation.py +0 -0
  484. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1312_engine_costs.py +0 -0
  485. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1325_nominal_agreement.py +0 -0
  486. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1332_overlap_remedy.py +0 -0
  487. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1332_zone_labels.py +0 -0
  488. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1334_prevent_ink.py +0 -0
  489. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1336_grm03_ap242_pmi_fixture.py +0 -0
  490. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1338_scale_before_page_escalation.py +0 -0
  491. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1349_precision_display.py +0 -0
  492. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1350_detected_takeover.py +0 -0
  493. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1353_cnc_authoritative_workflow.py +0 -0
  494. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1360_thread_depth.py +0 -0
  495. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1390_sheet_registration.py +0 -0
  496. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1395_degenerate_iso_region.py +0 -0
  497. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1396_layout_advisories.py +0 -0
  498. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_cli_report_sidecar.py +0 -0
  499. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_1438_report_writer.py +0 -0
  500. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_367_leader_ink.py +0 -0
  501. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_443_grm03_axial_coverage.py +0 -0
  502. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_563_placement_intent.py +0 -0
  503. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
  504. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_798_floor_cardinality.py +0 -0
  505. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_798_material_field.py +0 -0
  506. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_924_zero_length_shoulders.py +0 -0
  507. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_issue_955_height_contingency.py +0 -0
  508. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_label_provenance.py +0 -0
  509. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_layout.py +0 -0
  510. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_layout_cleanliness.py +0 -0
  511. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_layout_hypothesis.py +0 -0
  512. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_layout_property.py +0 -0
  513. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_leader_footprint.py +0 -0
  514. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_lint_box_cache.py +0 -0
  515. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_lint_ink_overlap.py +0 -0
  516. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_lint_reconciliation.py +0 -0
  517. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_lint_structural.py +0 -0
  518. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_linting.py +0 -0
  519. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_location_vocabulary.py +0 -0
  520. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_note_verb.py +0 -0
  521. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_object_aspects.py +0 -0
  522. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_occupancy_boxes.py +0 -0
  523. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_part_model.py +0 -0
  524. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pmi.py +0 -0
  525. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pmi_datum_lowering.py +0 -0
  526. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pmi_gtol_lowering.py +0 -0
  527. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pmi_part21.py +0 -0
  528. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_pocket_pattern.py +0 -0
  529. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_principal_profile_classifier.py +0 -0
  530. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_private_test_attr_reads.py +0 -0
  531. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_private_test_imports.py +0 -0
  532. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_refactor_golden.py +0 -0
  533. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_registry.py +0 -0
  534. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_render_seam.py +0 -0
  535. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_repack_geometry_seam.py +0 -0
  536. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_script_detail_parity.py +0 -0
  537. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_shared_box_memo.py +0 -0
  538. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_gdt.py +0 -0
  539. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_notes.py +0 -0
  540. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_of.py +0 -0
  541. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_section.py +0 -0
  542. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_sheet_tables.py +0 -0
  543. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_slot_pattern.py +0 -0
  544. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_soft_deprecation.py +0 -0
  545. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_solve_trace.py +0 -0
  546. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_step_analysis_evaluation.py +0 -0
  547. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_suppression_marks.py +0 -0
  548. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_view_plan.py +0 -0
  549. {draftwright-0.4.19 → draftwright-0.4.21}/tests/test_witness_label_reconciliation.py +0 -0
@@ -154,6 +154,23 @@
154
154
 
155
155
  ### Changed
156
156
 
157
+ - Production recognition now consumes published `quiddity==0.2.2`. Unified section-recess
158
+ occurrences and their same-run patterns feed the existing pocket, channel and blind-slot
159
+ drawing grammar. Original occurrence ownership, independent completeness and explicit
160
+ unsupported/refusal outcomes follow that single aggregate (#1471).
161
+ - Machine-readable reports and STEP inspection documents advance to schema v2 because their
162
+ closed producer object now names `quiddity`. The schema-v1 documents remain available for
163
+ existing files; readers must select the schema using `schema_version` (#1471).
164
+ - Groove membership now retains Quiddity's body-local profile identity. Generated declarations
165
+ use `profile_group` to associate coaxial grooves and steps without copying provider keys.
166
+ Omitted steps do not cause a groove to attach to another body (#1471).
167
+ - Known limitations in Quiddity 0.2.2: some mixed-profile/nested pockets, bore-intersected channels
168
+ and edge-open recesses, and pockets in cylindrical stock can lose automatic annotations.
169
+ Refusals remain visible in lint and evidence. Regression cases are retained as strict expected
170
+ failures while upstream [#536](https://github.com/pzfreo/quiddity/issues/536),
171
+ [#538](https://github.com/pzfreo/quiddity/issues/538) and
172
+ [#541](https://github.com/pzfreo/quiddity/issues/541) are open.
173
+
157
174
  - Accepted schema-v3 straight or circular `Blend` chains, including concave occurrences, now cross
158
175
  a dedicated end-to-end consumer path:
159
176
  `BlendFeature`, explicit `Sheet.blend(...)`, executable generated declarations, one
@@ -167,7 +184,7 @@
167
184
  also retains circular paths, while raw arbitrarily rotated circular recognition remains an
168
185
  upstream limitation (b123d-recognisers#491) (#1433; ADRs 0011, 0013–0017, 0020).
169
186
 
170
- - Draftwright now exactly pins the immutable `b123d-recognisers` 0.4.14 release and advances its
187
+ - The preceding recognition update pinned the immutable `b123d-recognisers` 0.4.14 release and advanced its
171
188
  fail-closed capability and inspection joins. `Blend` schema v3 replaces the old flat cylindrical
172
189
  fields with exact `StraightBlendPath` and `CircularBlendPath` records and admits proved concave
173
190
  and toroidal occurrences; Draftwright preserves those semantics through IR, `Sheet.blend(...)`,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: draftwright
3
- Version: 0.4.19
3
+ Version: 0.4.21
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,13 +684,13 @@ 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.4.14
688
687
  Requires-Dist: build123d-drafting-helpers>=0.14.2
689
688
  Requires-Dist: build123d<0.11,>=0.9.0; python_full_version < '3.13'
690
689
  Requires-Dist: build123d<0.12,>=0.11; python_full_version >= '3.13'
691
690
  Requires-Dist: numpy>=1.24
692
691
  Requires-Dist: pillow>=10
693
692
  Requires-Dist: pypdfium2>=4
693
+ Requires-Dist: quiddity==0.2.4
694
694
  Requires-Dist: reportlab>=4.0
695
695
  Requires-Dist: steputils==0.1
696
696
  Requires-Dist: svglib>=1.5
@@ -1001,12 +1001,12 @@ builds on three libraries:
1001
1001
 
1002
1002
  ```
1003
1003
  draftwright
1004
- └── b123d-recognisers — deterministic geometry recognition
1004
+ └── quiddity — deterministic geometry recognition
1005
1005
  └── build123d-drafting-helpers — Dimension, Leader, HoleCallout, …
1006
1006
  └── build123d — CAD kernel
1007
1007
  ```
1008
1008
 
1009
- Geometry recognition lives in the Apache-2.0 `b123d-recognisers` package. Draftwright owns
1009
+ Geometry recognition lives in the Apache-2.0 `quiddity` package. Draftwright owns
1010
1010
  the per-build recognition cache, record→IR conversion, drafting policy, and linting
1011
1011
  (`linting/`); annotation primitives (`Dimension`, `Leader`, etc.) live in
1012
1012
  `build123d-drafting-helpers` and can be used independently. The compiler is largely converged
@@ -301,12 +301,12 @@ builds on three libraries:
301
301
 
302
302
  ```
303
303
  draftwright
304
- └── b123d-recognisers — deterministic geometry recognition
304
+ └── quiddity — deterministic geometry recognition
305
305
  └── build123d-drafting-helpers — Dimension, Leader, HoleCallout, …
306
306
  └── build123d — CAD kernel
307
307
  ```
308
308
 
309
- Geometry recognition lives in the Apache-2.0 `b123d-recognisers` package. Draftwright owns
309
+ Geometry recognition lives in the Apache-2.0 `quiddity` package. Draftwright owns
310
310
  the per-build recognition cache, record→IR conversion, drafting policy, and linting
311
311
  (`linting/`); annotation primitives (`Dimension`, `Leader`, etc.) live in
312
312
  `build123d-drafting-helpers` and can be used independently. The compiler is largely converged
@@ -1,6 +1,6 @@
1
1
  # Recogniser capability contract
2
2
 
3
- Draftwright consumes the public capability manifest installed with `b123d-recognisers`; it never
3
+ Draftwright consumes the public capability manifest installed with `quiddity`; it never
4
4
  reads a sibling checkout or a package-private file. The matching Draftwright-owned declaration is
5
5
  implemented in `draftwright.recogniser_contract` and validated in CI.
6
6
 
@@ -14,7 +14,7 @@ library.
14
14
  Declared-feature geometry reads use a different public boundary. The installed package's
15
15
  inspection manifest format 1 is joined to the separate Draftwright-owned declaration in
16
16
  `draftwright.inspection_contract`. That contract admits inspection API major 1 and exactly the
17
- consumed `b123d_recognisers.inspection` symbol schemas: the five geometry readers, their public
17
+ consumed `quiddity.inspection` symbol schemas: the five geometry readers, their public
18
18
  result/error types, the cylindrical surface parameter layout, bevel rejection reasons, and the
19
19
  semantic names and units of the Double-D tuple. It also checks the exact installed package
20
20
  version. Recognition-family policy does not leak into this smaller measurement contract, and an
@@ -59,7 +59,7 @@ Validation fails closed and names the family and boundary whenever possible:
59
59
  ## Adding or changing a recogniser
60
60
 
61
61
  For an additive field that increments an existing record schema, update the relevant Draftwright
62
- adapter and declaration when advancing the exact `b123d-recognisers` dependency pin. Tests must
62
+ adapter and declaration when advancing the exact `quiddity` dependency pin. Tests must
63
63
  prove the installed schema is accepted while later schemas still fail. The package version belongs
64
64
  only in `pyproject.toml` and `uv.lock`; the capability declaration derives runtime identities from
65
65
  installed package metadata.
@@ -70,39 +70,58 @@ issue. The contract test derives package record outputs, converter registries, l
70
70
  and emitter branches independently, so copying a new name into the declaration alone cannot make CI
71
71
  pass.
72
72
 
73
- ### Quiddity migration baseline
74
-
75
- The first [#1471](https://github.com/pzfreo/draftwright/issues/1471) migration slice tests the
76
- released Quiddity SectionRecess document against the existing authored pocket corpus. Quiddity is
77
- pinned in the development dependencies for this comparison. Production continues to use the
78
- existing recogniser dependency and capability declaration.
79
-
80
- The private pocket adapter in `model/detect.py` reads primitive schema-2 occurrence geometry and
81
- produces the existing `PocketFeature`. It admits principal-axis closed rectangles and open
82
- rectangular corner/edge chains, preserves the opening direction, and refuses unsupported shapes,
83
- sloped ends, invalid frames and malformed measurements. An open chain remains edge-anchored; its
84
- missing boundary is never reconstructed as a physical edge.
85
-
86
- `tests/test_issue_1471_section_recess_pockets.py` checks independently authored dimensions,
87
- opposed and side openings, disconnected bodies, topology variants, the existing drawing path,
88
- executed generated Sheet scripts and authored omission. The baseline tests for pocket patterns,
89
- channels and both blind-slot families remain the acceptance floor for their later adapters.
90
-
91
- This is preparation for adoption, not a new automatic detection mode. The adapter does not yet
92
- participate in the production registry, bind occurrence ownership or provide Quiddity-based lint.
93
- Its comparison drawings use the pinned provider for physical critique. The eventual cutover must
94
- validate result-local references, bind exact same-run occurrences, migrate patterns and explicit
95
- refusals, and update independent lint, reports and inspection together. A build already holding an
96
- aggregate must project it rather than invoke the document builder for a second recognition run.
97
-
98
- The comparison pins Quiddity 0.2.1, which fixes
99
- [Quiddity #505](https://github.com/pzfreo/quiddity/issues/505): support proofs now handle
100
- build123d 0.10 `ShapeList` boolean results. The pocket corpus exercises this public recognition
101
- path across the supported Python/build123d matrix before consumer adaptation.
102
-
103
- `bosses` is the fully consumed reference family. `repeating-radial-profiles` is the opposite
104
- reference: it remains geometry-only critique evidence for a separately authored gear declaration,
105
- with no inferred gear feature added to fill the table.
73
+ ### Quiddity 0.2.4 runtime contract
74
+
75
+ [#1486](https://github.com/pzfreo/draftwright/pull/1486) adopts the published
76
+ `quiddity==0.2.4` package after the migration in
77
+ [#1471](https://github.com/pzfreo/draftwright/issues/1471). Its public `quiddity`, `quiddity.evidence` and
78
+ `quiddity.inspection` surfaces supply recognition, exact occurrence evidence and declared geometry
79
+ reads. There is one recognition aggregate per build; consumers project that result rather than
80
+ calling the document builder to obtain another run.
81
+
82
+ The manifest has 27 families. One `section-recesses` family replaces the former pockets, pocket
83
+ patterns, channels, rectangular and round-bottom blind slots, passages and prismatic pockets.
84
+ `RecognitionResult.section_recesses` contains the immutable occurrences;
85
+ `section_recess_patterns` relates them by run-local occurrence indices; `section_recess_refusals`
86
+ retains the provider's explicit reasons for refusing candidate geometry. The public document
87
+ builder is a serialization front door, not another feature family or a production rescan.
88
+
89
+ The shared adapter reads the published frame, profile, run interval and ends and lowers supported
90
+ principal-axis geometry to the existing pocket, channel and blind-slot IR. It preserves the opening
91
+ direction and edge anchoring and rejects malformed records. Supported rounded rectangular pockets
92
+ retain their corner radius, and supported cylindrical-mouth pockets carry maximum-depth intent
93
+ rather than an invented uniform depth. Valid profiles and end shapes outside the drafting grammar
94
+ remain explicit unsupported outcomes, including the two-plane passage cases. Pattern members resolve
95
+ to the original records in the same aggregate before they share a drawing owner. Missing members,
96
+ duplicate indices, cross-body grouping and inconsistent lattice geometry fail closed.
97
+
98
+ Independent pocket and pattern corpora, channel ownership tests and both blind-slot corpora check
99
+ measurements, public declarations, executed generated code and the placed requirement ledger.
100
+ Recognition refusals retain source provenance and contribute an unsupported outcome without a
101
+ fabricated position. Report and inspection schema v2 name `producer.quiddity`; their v1 schemas
102
+ remain available for existing documents.
103
+
104
+ The common-part restoration checks the five rounded tuner-jig pockets and their grouped callout,
105
+ corner radii, pitch and absolute locations; pockets cut into cylindrical stock; and the pierced
106
+ U-channel's supported channel measurements. Automatic recognition, declared input and executed
107
+ Sheet scripts retain the supported recess facts. These checks do not turn a successfully rendered
108
+ part into a completeness guarantee.
109
+
110
+ The preceding Draftwright 0.4.20 / Quiddity 0.2.2 release documented annotation losses for mixed
111
+ and nested pockets ([Quiddity #536](https://github.com/pzfreo/quiddity/issues/536)), bore-intersected
112
+ or edge-open recesses ([#538](https://github.com/pzfreo/quiddity/issues/538)), and pockets in
113
+ cylindrical stock ([#541](https://github.com/pzfreo/quiddity/issues/541)). Those historical limitations
114
+ must not be used to excuse the common cases restored in #1486. Conversely, recognising more source
115
+ profiles does not imply that every profile now has a supported drafting grammar. General complex
116
+ pockets and nonuniform passages can still produce explicit unsupported requirements.
117
+
118
+ Check the source occurrence outcomes, placed requirements and lint for affected geometry.
119
+ Regression expectations are reassessed per fixture: a restored supported case must pass, while an
120
+ unsupported case must retain its truthful diagnostic rather than an approximate old annotation.
121
+ Recognition, declaration, placement, reporting and coverage checks remain release gates.
122
+
123
+ `bosses` remains a fully consumed reference family. `repeating-radial-profiles` remains geometry-only
124
+ critique evidence for a separately authored gear declaration, with no inferred gear feature.
106
125
 
107
126
  ## Hole completeness evidence
108
127
 
@@ -205,11 +224,11 @@ independent score.
205
224
 
206
225
  ## Pocket completeness evidence
207
226
 
208
- The lone `pockets` completeness boundary is independently `supported` from
227
+ The lone-pocket grammar within `section-recesses` is independently `supported` from
209
228
  `tests/fixtures/evaluation/corpus-pockets-v1.json`. Ten construction-authored cases contribute 13
210
229
  physical pockets, 52 parameter checks and 52 downstream checks. The corpus covers a through-slot
211
230
  negative, one off-centre pocket, an edge-anchored corner interruption, equal independent pockets,
212
- opposite openings, a principal side opening, a PrismaticPocket ownership negative, separate
231
+ opposite openings, a principal side opening, an unsupported polygonal-pocket ownership negative, separate
213
232
  compound bodies and a reverse-serialized topology pair.
214
233
 
215
234
  Identity uses width/long/depth axes, opening sign and physical location; width, length, depth and
@@ -223,7 +242,7 @@ single public `location` authoring unit.
223
242
 
224
243
  ## Pocket-pattern completeness evidence
225
244
 
226
- The `pocket-patterns` completeness boundary is independently `supported` from
245
+ The pocket-pattern grammar within `section-recesses` is independently `supported` from
227
246
  `tests/fixtures/evaluation/corpus-pocket-patterns-v1.json`. Seven construction-authored cases
228
247
  cover 30° linear and rectangular-grid positives, the two-member threshold, unequal-spacing
229
248
  ambiguity, a plain negative, an axis-aligned underside compound case and a reverse-serialized
@@ -260,6 +279,14 @@ its diameter is drafted once. Removing provider grooves, changing width/diameter
260
279
  corrupting declaration or generated code, or severing either measurement claim reduces the
261
280
  corresponding independent layer.
262
281
 
282
+ Quiddity's optional `Groove.profile` key now identifies the exact body-local turned profile.
283
+ The compiler and independent axial/step ledgers use that key and still cross-check the published
284
+ axis line and axial band. Missing profile identity retains the geometric ambiguity refusal;
285
+ a missing profile in an authored subset cannot redirect the groove to another coaxial body.
286
+ Generated declarations replace the provider key with the same `profile_group` token used for the
287
+ owning steps. The keyed nested-body and omission checks live in
288
+ `tests/test_issue_1471_groove_profile.py`; they supplement the unchanged authored groove corpus.
289
+
263
290
  ## Rectangular-pad completeness evidence
264
291
 
265
292
  The `rectangular-pads` completeness boundary is independently `supported` from
@@ -535,27 +562,10 @@ position. Removing any one of those five physical facts produces
535
562
  independently authored rectangular-pad detection/parameter/downstream benchmark corpus required
536
563
  before claiming family-level completeness.
537
564
 
538
- ## Recognisers 0.4.10 adoption and blind-slot boundary
539
-
540
- Draftwright exactly pins `b123d-recognisers==0.4.10`. The 28 family record schemas already
541
- consumed from 0.4.9 are unchanged. The inspection namespace remains format 1 / API major 1;
542
- Draftwright advances its exact package join without widening the set of inspection symbols it
543
- consumes. The additive `b123d_recognisers.evidence` API is public provider capability, but this
544
- adoption does not consume it before a concrete correspondence slice demonstrates that need.
545
-
546
- Unchanged record schemas do not mean byte-identical recognition output. The 0.4.10 provider closes
547
- slot-depth, subdivided paired-ramp/AngledStep, and noisy stubby-pocket gaps and fixes Double-D/Hole
548
- ownership, external-cone countersink false positives, Plate tie covariance, and turned-step
549
- translation covariance. Draftwright accepts those public aggregate outcomes: its consumer tests pin
550
- that an external cone no longer creates a countersink requirement and that an edge-open rectangular
551
- recess now yields to the dedicated blind-slot owner instead of retaining a false `Pocket` callout.
552
- The provider's immutable
553
- [0.4.10 release](https://github.com/pzfreo/b123d-recognisers/releases/tag/v0.4.10) owns the lower-level
554
- recognition predicates and counterexamples; Draftwright does not duplicate private provider
555
- algorithms to restate them.
556
-
557
- The release adds `rectangular-blind-slots` and `round-bottom-blind-slots` to the one aggregate.
558
- Both now have dedicated Draftwright feature types and public Sheet words. The rectangular family
565
+ ## Blind-slot drawing grammar
566
+
567
+ Quiddity publishes both blind-slot shapes as `SectionRecess` occurrences in the unified inventory.
568
+ Their consumer contracts remain distinct. Both now have dedicated Draftwright feature types and public Sheet words. The rectangular family
559
569
  uses `RectangularBlindSlotFeature` and
560
570
  `Sheet.rectangular_blind_slot(...)` declaration, generated-code round trip and solver-owned
561
571
  `OPEN SLOT width × capped-run × depth DEEP` callout. Its axes and opening signs remain structural
@@ -583,14 +593,11 @@ with exact full-record correspondence and parameter/outcome provenance under the
583
593
  rules as the rectangular family. It now participates independently in `audited_score`; ordinary
584
594
  slots, pockets, channels and rectangular blind slots do not share ownership.
585
595
 
586
- ## Recognisers 0.4.14 adoption and path-complete Blends
596
+ ## Path-complete Blend drawing grammar
587
597
 
588
- Draftwright exactly pins `b123d-recognisers==0.4.14`; the provider family count remains 33 and
589
- the inspection API remains format 1 / major 1. The fail-closed record join now accepts `Blend`
590
- schema v3 with nested `StraightBlendPath` and `CircularBlendPath` schema-v1 records. It also
591
- accepts `PassageEnds`, `PassageSection`, and `SectionPassage` schema v2. Passage remains explicitly
592
- unsupported under #1245: accepting its released structural schema does not invent an IR feature,
593
- Sheet declaration, or completeness credit.
598
+ Quiddity 0.2.2 retains `Blend` schema v3 with nested `StraightBlendPath` and
599
+ `CircularBlendPath` schema-v1 records. The installed manifest and the independently declared
600
+ consumer schemas must agree before these records can reach drawing generation.
594
601
 
595
602
  The supported Blend adapter preserves the complete discriminated path. Straight occurrences keep
596
603
  their canonical line direction and anchor; circular occurrences keep their centre, canonical
@@ -618,12 +625,13 @@ the complete canonical `axis_direction`; `Sheet.blend(...)`, generated replay an
618
625
  solver-owned `n× R` leader preserve it without pretending it is a legacy Fillet. Exact occurrence
619
626
  and measurement provenance place Blend in `audited_score`.
620
627
 
621
- `oriented_slots` and `oriented_slot_patterns` remain separately registered as undecided under
622
- #1430. Their real occurrences are visible in `unscored_recognized_families`, but contribute no
623
- invented requirement. The free-axis slot record retains vector width/long directions and its
624
- authoritative `SectionPassage` source; array/grid records retain those member identities and their
625
- vector lattice. Coercing either into principal-axis `SlotFeature` / `SlotPatternFeature` would
626
- discard that contract, so no Sheet word or completeness claim exists for them on main.
628
+ Standalone `oriented_slots` are supported through dedicated vector-valued IR, the public
629
+ `Sheet.oriented_slot(...)` declaration, executable generated code, two compiler-approved width/length
630
+ requirements, and solver-owned leaders. Exact run-local identity binds each accepted record to its
631
+ IR owner. Array/grid members are excluded by exact provider-record membership and retain the
632
+ still-deferred `oriented-slot-patterns` policy; they are not emitted as competing singletons.
633
+ The shared requirement ledger feeds both lint and reports. Malformed or copied pattern authority
634
+ is refused rather than reconstructed from equal geometry.
627
635
 
628
636
  The existing schema-v1 `PairedRampStep` record is unchanged, while 0.4.12 expands provider
629
637
  recognition to shallow nonzero ramp pairs. A released shallow specimen now crosses the already
@@ -657,7 +665,7 @@ height/shoulder projection. The aggregate face-level and riser families remain s
657
665
  outcome says only that each raw evidence record is not itself an independent inferred feature or
658
666
  completeness requirement. It adds no Sheet word, IR adapter, drawing ink, or provider API.
659
667
 
660
- ## Recognisers 0.4.9 prepared frame boundary
668
+ ## Historical: recognisers 0.4.9 prepared frame boundary
661
669
 
662
670
  Draftwright's 0.4.9 boundary accepted `RiserEvidence` v2,
663
671
  `TurnedStep`/`TurnedProfile` v2, and the nested `TurnedProfileKey` v1. These records preserve
@@ -705,51 +713,26 @@ Sheet declaration, generated code or annotation, and emits
705
713
  occurrence contributes one `unsupported` completeness requirement. Issue #1247 records this
706
714
  consumer decision.
707
715
 
708
- ## Prismatic-pocket boundary
709
-
710
- The installed aggregate reconciles the two pocket inventories before Draftwright sees them. A
711
- candidate reported by both direct recognisers yields to the supported `Pocket` record;
712
- `RecognitionResult.prismatic_pockets` therefore contains occurrences not owned by `Pocket`.
713
- Draftwright consumes that aggregate policy and does not repeat provider reconciliation. This is an
714
- ownership statement, not a shape classification: for example, a rotated four-sided recess can
715
- remain a `PrismaticPocket` when the axis-paired `Pocket` recogniser does not accept it.
716
-
717
- The remaining `PrismaticPocket.section` may be any planar polygon. The rectangular pocket grammar
718
- `W × L × D DEEP` is false for a triangle, while an across-flats callout applies only to selected
719
- regular polygons and cannot represent the general record. Draftwright therefore retains the family
720
- disposition as `unsupported`: it creates no inferred IR feature, Sheet declaration, generated code,
721
- or drawing annotation. Each aggregate occurrence instead emits
722
- `prismatic_pocket_requirement_unsupported` at warning severity and contributes one `unsupported`
723
- completeness requirement. Exact mouth-to-section correlation replaces the generic unsupported-
724
- profile warning only for that occurrence, so an unrelated unrecognised profile remains visible.
725
-
726
- ## Passage compatibility boundary
727
-
728
- The installed `b123d-recognisers==0.4.14` release contains the `passages` family introduced
729
- in 0.2.6. Version 0.4.0 made `SectionPassage` the authoritative physical output; 0.4.14 publishes
730
- its nested schema v2 and retains `Passage` as a compatibility projection. Draftwright declares all
731
- six public and nested record schemas exhaustively but deliberately keeps the family `unsupported`,
732
- with the drafting decision recorded by issue #1245. This is a truthful consumer disposition: both
733
- aggregate inventories remain visible, but only authoritative `section_passages` contributes an explicitly
734
- `unsupported` completeness requirement. Draftwright does not invent an IR feature, DSL
735
- declaration, generated code, or drawing annotation for either inventory.
736
-
737
- The 0.4 contract is explicit:
738
-
739
- - `SectionPassage` will be the authoritative physical output and aggregate census source;
740
- - legacy `Passage` values will be an accepted-only compatibility projection;
741
- - `recognise_passages(..., ledger=...)` will be a fail-loud unavailable compatibility operation;
742
- - the writer-free `recognise_passages` name will remain public but non-authoritative; and
743
- - rich split-junction passages can supersede a Slot claim, moving physical ownership to the
744
- unsupported Passage family through `SLOT_SUPERSEDED_BY_PASSAGE`.
745
-
746
- The exact 0.4.14 pin, manifest-v2 validator and explicit unsupported inventories make that limitation
747
- fail-visible rather than silently treating rich passages as supported. Draftwright deliberately
748
- does not claim that a regular-polygon `HEX … A/F THRU` callout covers the complete line/arc section
749
- schema. Each authoritative `RecognitionResult.section_passages` occurrence therefore emits
750
- `passage_requirement_unsupported` at warning severity and contributes an `unsupported` requirement
751
- to the completeness component. The accepted-only legacy `.passages` projection contributes neither
752
- a second issue nor a second requirement. Issue #1245 records this consumer decision.
716
+ ## Unsupported polygonal-pocket and passage grammar
717
+
718
+ Quiddity's unified `SectionRecess` inventory carries both supported and unsupported profile
719
+ geometry. Draftwright selects its existing drawing grammar from the exact public section and ends;
720
+ it does not rerun provider recognition or retain a second legacy pocket/passage inventory.
721
+
722
+ A general polygonal recess has no truthful rectangular `W × L × D DEEP` callout. A general line/arc
723
+ through-opening likewise cannot be represented by a regular-polygon `HEX … A/F THRU` callout.
724
+ These occurrences retain the decisions recorded by #1246 and #1245: no inferred IR feature, public
725
+ declaration, generated feature or annotation is invented. Each occurrence instead contributes one
726
+ `unsupported` completeness outcome and its corresponding `prismatic_pocket_requirement_unsupported`
727
+ or `passage_requirement_unsupported` warning. Exact mouth-to-section correlation can replace a
728
+ generic unsupported-profile warning for that occurrence; unrelated unrecognised geometry remains
729
+ visible. The old accepted-only Passage projection no longer exists and cannot add another count.
730
+
731
+ Provider refusals are distinct from accepted geometry outside the drawing grammar. Each exact
732
+ `SectionRecessRefusal` is retained with its reason and original evidence, emits
733
+ `section_recess_recognition_refused`, and carries no fabricated feature position. A valid unmatched
734
+ supported recess still contributes its full independent requirement count. A malformed recess
735
+ cannot establish a trustworthy family or denominator and is rejected at intake.
753
736
 
754
737
  ## Step families introduced in recognisers 0.4.6
755
738
 
@@ -4,8 +4,146 @@
4
4
  are documented here because they are part of normal use even though their Python names begin
5
5
  with an underscore.
6
6
 
7
+ ## Grooves on coaxial bodies
8
+
9
+ When different turned bodies share an axis line, give their steps distinct `profile_group`
10
+ values and use the owning body's value on `s.groove(..., profile_group="outer")`.
11
+ The token associates features; it does not specify an annotation position or add a measurement.
12
+ Generated scripts preserve this association using Draftwright-owned tokens instead of provider
13
+ keys. A groove can still be declared when the authored set omits all of that body's steps.
14
+
15
+ ## Checking dimension placement rules
16
+
17
+ Call `handle.dimension_ids()` to find the measurements a declared feature exposes, then
18
+ query a measurement before choosing its placement controls:
19
+
20
+ ```python
21
+ options = s.dimension_options(hole, "bore.diameter")
22
+ # options["placements"] contains pairs accepted by the planner's placement rules.
23
+ # None means leave that override unspecified.
24
+
25
+ check = s.validate_dimension(hole, "bore.diameter", view="plan", side="left")
26
+ if check["supported"]:
27
+ s.dimension(hole, "bore.diameter", view="plan", side="left")
28
+ else:
29
+ print(check["issues"], check["options"])
30
+ ```
31
+
32
+ Both queries return versioned JSON-ready dictionaries without recording intent, preparing the
33
+ Sheet, recognising geometry or rendering. Use complete view/side pairs: a side supported in one
34
+ view may be unavailable in another. The `axis` argument follows `dimension()`'s parameter-variant
35
+ rules; full parameter ids already name their variant. Location intent currently admits no view
36
+ or side override. Invalid references, unsupported controls and unsupported placement pairs have
37
+ separate structured refusal codes in `validate_dimension()`; `dimension_options()` raises on an
38
+ invalid reference.
39
+
40
+ Hole-size callouts in the plan and side views accept `left` or `right`. The overall
41
+ envelope height accepts `left` or `right` in the front view. These hints can separate
42
+ hole sizes from vertical location dimensions without moving annotation coordinates:
43
+
44
+ ```python
45
+ sheet.dimension(lower_hole, "bore.diameter", side="left")
46
+ sheet.dimension(upper_hole, "bore.diameter", side="left")
47
+ sheet.dimension(envelope, "height.length", side="left")
48
+ sheet.dimension(lower_hole, "location")
49
+ sheet.dimension(upper_hole, "location")
50
+ ```
51
+
52
+ Each side belongs to its named view: the front-view height and side-view hole sizes
53
+ occupy different boundaries. The layout reserves space for the left height and short
54
+ step rises together before choosing scale and page. The shared solver places the
55
+ annotations within those boundaries; generated scripts retain the authored sides.
56
+ An explicit side is a constraint: an infeasible placement reports the affected
57
+ measurement instead of silently choosing the opposite boundary. Repair preserves an
58
+ authored overall-height side, including after a label adjustment.
59
+
60
+ The explicit `single_dimension_placement_rules` scope means `supported` reports acceptance by
61
+ the current planner placement rules. Both documents set `requires_build_validation: true`:
62
+ whole-part classification can select a different renderer, so this query does not prove actual
63
+ rendered support. For example, a boss on a turned part can use a different diameter renderer
64
+ from a boss on a prismatic part. Agreement with other authored dimensions, visibility in an
65
+ authored view set, available space, completeness and collision-free placement also require a
66
+ build. Build and lint still assess the resulting Sheet. A
67
+ query never replaces an existing dimension request. Keep the original feature handle for edits;
68
+ these reports do not introduce persistent feature identities or new lane, route or pin controls.
69
+
70
+ ## Selecting a hole location component
71
+
72
+ Use `location` alone to request the usual location set. To select one component of a hole
73
+ group or pattern, pair its declared member index with the measured world axis:
74
+
75
+ ```python
76
+ options = sheet.dimension_options(holes, "location")
77
+ print(options["location_components"]) # valid member/axis pairs and their parameter ids
78
+ sheet.dimension(holes, "location", member=1, axis="y")
79
+ ```
80
+
81
+ Member indices start at zero and refer to the declared `members` tuple. A singleton hole
82
+ has member 0. The axis is transverse to the hole's own axis: an X-directed hole can have
83
+ Y and Z location dimensions. A bolt-circle pattern also accepts `member="centre"`.
84
+ Both selectors are required for a fine request; invalid members or axes are refused.
85
+ The existing `validate_dimension()` query accepts the same selectors.
86
+
87
+ The coarse pattern request keeps its automatic anchor policy: the member nearest the
88
+ datum, or the centre of a bolt circle. Adding a fine request selects that extra component
89
+ without selecting its sibling axis. Repeating a request does not duplicate a measurement.
90
+ Generated scripts carry the member and axis so removing one location declaration omits
91
+ that component. Coincident dimensions can share one mark while recording every approved
92
+ owner.
93
+
94
+ These indices address one declaration and its generated script. They do not establish
95
+ correspondence across unrelated recognition runs. The shared solver still chooses where
96
+ to place the dimension; location selection supplies no page coordinates.
97
+
7
98
  ## Sheet
8
99
 
100
+ ### Comparing measurements after a declaration edit
101
+
102
+ `compare_measurements()` compares named compiled measurements, including their owner,
103
+ parameter, nominal value, tolerance, directional span and rendered claim text. Linear
104
+ dimensions also retain their measured path lengths in model units, so exchanging labels
105
+ between two spans cannot hide behind an unchanged label multiset. Recorded per-annotation
106
+ spans and location components also distinguish equal-valued axes under a coarse parameter
107
+ id. These are provenance claims; independent lint must still check physical targets.
108
+ Reuse the feature objects in a declaration when editing placement intent:
109
+
110
+ ```python
111
+ from dataclasses import replace
112
+ from draftwright import build_drawing
113
+ from draftwright.audit import compare_measurements
114
+
115
+ original_model = sheet.model()
116
+ edited_model = replace(
117
+ original_model,
118
+ authored_dimensions=tuple(
119
+ replace(request, side="left") if request.role == "height.length" else request
120
+ for request in original_model.authored_dimensions
121
+ ),
122
+ )
123
+ before = build_drawing(part, model=original_model)
124
+ after = build_drawing(part, model=edited_model)
125
+ result = compare_measurements(before, after)
126
+ print(result["status"], result["lost"], result["changed"], result["unknown"])
127
+ ```
128
+
129
+ The status is `preserved`, `changed` or `unknown`. An unresolved owner or unconfirmed
130
+ claim prevents `preserved`. For an in-place edit, capture
131
+ `before = drawing.measurement_snapshot()` before changing the drawing, then compare
132
+ that snapshot with the edited drawing. Snapshots retain process-local feature references.
133
+
134
+ Separately rebuilt declarations do not acquire correspondence from equal geometry or
135
+ inventory order. If the caller knows the correspondence, pass
136
+ `feature_pairs=((old_feature, new_feature), ...)`. Each pair must name exact owners in
137
+ the respective snapshots and the correspondence must be one-to-one. These are caller
138
+ assertions; the comparison checks measurement meaning under them. Output owner numbers
139
+ are positions in the before snapshot for presentation, not durable identities.
140
+
141
+ `diff_builds()` includes this result as `measurement_comparison` and detects same-kind
142
+ substitutions between shared declared owners. A clear annotation diff can still have
143
+ unknown measurement correspondence. Use independent `lint_summary()["quality"]`
144
+ evidence alongside the comparison: named-measurement preservation does not establish
145
+ physical completeness, pin preservation or release readiness.
146
+
9
147
  ::: draftwright.sheet.Sheet
10
148
  options:
11
149
  filters: public
@@ -156,6 +294,13 @@ explicit declaration has the same exact occurrence identity and view routing as
156
294
  record.
157
295
  Generated Sheet code preserves every field.
158
296
 
297
+ Straight-path radius leaders target curved boundaries of the physical cylindrical patch.
298
+ Their `at` value locates the analytic axis, not the arrow tip. If a declared support is missing
299
+ or ambiguous, the engine reports `blend_dropped`. Physical lint reports
300
+ `radius_leader_target_mismatch` when a placed tip misses its trimmed boundary, or
301
+ `radius_leader_target_unverifiable` when that boundary cannot be established; these findings
302
+ lower fidelity. Circular-path toroidal blends retain their separate tangency selection.
303
+
159
304
  These are part-space feature coordinates, never page positions. The annotation placement solve
160
305
  owns the final leader and label coordinates. The word is explicit-only because detached surface
161
306
  geometry cannot prove a complete chain or the provider aggregate's Fillet precedence.
@@ -303,3 +448,13 @@ with the canonical feature diameter, using the same rule as planning. A larger m
303
448
  keeps the original source value and identity in a blocked dimension; it does not replace
304
449
  the canonical value or crash planning. Generated Sheet scripts retain the blocker, and
305
450
  `authored_dim_source_unresolved` reports the withheld source dimension through lint.
451
+
452
+ ### Oriented through-slots
453
+
454
+ `Sheet.oriented_slot(...)` declares a rectangular through-slot with explicit width, long and
455
+ run directions and its retained passage geometry. Its two independently addressable
456
+ measurements are `oriented_slot_width.length` and `oriented_slot_length.length`; generated
457
+ Sheet scripts preserve those directions and the passage. The current drawing grammar requires
458
+ both run ends to be open and perpendicular to the run. Automatic conversion rejects a source
459
+ with a nonzero end-plane gradient, because the IR cannot retain that slope and a flat opening
460
+ would put the leader on the wrong physical rim.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "draftwright"
7
- version = "0.4.19"
7
+ version = "0.4.21"
8
8
  description = "Automated technical-drawing generation for build123d"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -18,7 +18,7 @@ dependencies = [
18
18
  "build123d>=0.9.0,<0.11 ; python_full_version < '3.13'",
19
19
  "build123d>=0.11,<0.12 ; python_full_version >= '3.13'",
20
20
  "build123d-drafting-helpers>=0.14.2",
21
- "b123d-recognisers==0.4.14",
21
+ "quiddity==0.2.4",
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
@@ -81,13 +81,15 @@ include = [
81
81
  [tool.pytest.ini_options]
82
82
  testpaths = ["tests"]
83
83
  timeout = 300
84
- # `slow` covers the heavy end-to-end builds over the large NIST CTC fixtures
84
+ # `slow` covers end-to-end integration builds, including the large NIST CTC fixtures
85
85
  # (minutes each), deselected by default. `smoke` is a curated, build-light subset
86
86
  # (~30 s) for a quick local "did I break something obvious" check — run it with
87
87
  # `uv run pytest -m smoke`. The default run is the full fast tier (`-m 'not slow'`,
88
- # ~8 min); CI owns that plus the slow tier across the OS/Python matrix.
88
+ # runtime depends on worker count). CI runs one real-part canary before merge,
89
+ # the full slow tier after merge, and the fast tier across its compatibility matrix.
89
90
  markers = [
90
- "slow: heavy end-to-end CTC fixture builds (deselected by default)",
91
+ "slow: end-to-end integration builds, including CTC fixtures (deselected by default)",
92
+ "real_part_canary: bounded real STEP semantic/export gate, selected once in PR CI",
91
93
  "smoke: curated build-light subset for a fast local check (~30 s)",
92
94
  "unit: pure-logic inner-loop tier — constructs NO OCC geometry (enforced by conftest, #656)",
93
95
  ]
@@ -169,8 +171,6 @@ dev = [
169
171
  "pytest-split>=0.8",
170
172
  "pytest-timeout>=2",
171
173
  "pytest-xdist>=3",
172
- # Released provider used by the migration parity tests; production remains on 0.4.14.
173
- "quiddity==0.2.1",
174
174
  "ruff>=0.4",
175
175
  "tomli>=2; python_version < '3.11'",
176
176
  ]