draftwright 0.4.27__tar.gz → 0.4.28__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 (601) hide show
  1. {draftwright-0.4.27 → draftwright-0.4.28}/CHANGELOG.md +15 -0
  2. {draftwright-0.4.27 → draftwright-0.4.28}/PKG-INFO +2 -2
  3. {draftwright-0.4.27 → draftwright-0.4.28}/docs/reference/recogniser-capabilities.md +16 -3
  4. {draftwright-0.4.27 → draftwright-0.4.28}/docs/reference/sheet.md +1 -1
  5. {draftwright-0.4.27 → draftwright-0.4.28}/pyproject.toml +2 -2
  6. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/_core.py +16 -2
  7. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/analysis.py +15 -3
  8. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/builder.py +34 -64
  9. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/cli.py +4 -1
  10. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/drawing.py +44 -0
  11. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/inspection_contract.py +1 -1
  12. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/__init__.py +6 -0
  13. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/coverage.py +111 -0
  14. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/pmi_coverage.py +91 -0
  15. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/quality.py +16 -0
  16. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/pmi.py +29 -0
  17. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/sheet.py +13 -1
  18. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/sheet_emit.py +16 -3
  19. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_inspection_contract.py +1 -1
  20. draftwright-0.4.28/tests/test_issue_1126_requesting_less_never_scores_better.py +99 -0
  21. draftwright-0.4.28/tests/test_issue_1132_turned_profile_span_is_reported.py +174 -0
  22. draftwright-0.4.28/tests/test_issue_1157_no_implicit_general_tolerance.py +140 -0
  23. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1217_the_facility_is_shared.py +3 -1
  24. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1296_cylindrical_diameter_pmi.py +11 -0
  25. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1298_manufacturing_requirements.py +5 -0
  26. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1357_plural_turned_profiles.py +12 -8
  27. draftwright-0.4.28/tests/test_issue_1555_turned_recognition_format_invariance.py +84 -0
  28. draftwright-0.4.28/tests/test_issue_1563_sheet_pmi_reconciliation.py +185 -0
  29. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_740_leader_assignment.py +17 -4
  30. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_make_drawing.py +61 -23
  31. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pmi.py +13 -0
  32. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_recogniser_capabilities.py +1 -1
  33. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_emit.py +6 -2
  34. {draftwright-0.4.27 → draftwright-0.4.28}/.gitignore +0 -0
  35. {draftwright-0.4.27 → draftwright-0.4.28}/LICENSE +0 -0
  36. {draftwright-0.4.27 → draftwright-0.4.28}/README.md +0 -0
  37. {draftwright-0.4.27 → draftwright-0.4.28}/docs/adr/README.md +0 -0
  38. {draftwright-0.4.27 → draftwright-0.4.28}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
  39. {draftwright-0.4.27 → draftwright-0.4.28}/skills/SKILL.md +0 -0
  40. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/__init__.py +0 -0
  41. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/_build_profile.py +0 -0
  42. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/_geometry.py +0 -0
  43. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/_pmi_part21.py +0 -0
  44. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/_warnings.py +0 -0
  45. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/angular_geometry.py +0 -0
  46. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotate.py +0 -0
  47. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/__init__.py +0 -0
  48. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/_common.py +0 -0
  49. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/angular.py +0 -0
  50. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/balloons.py +0 -0
  51. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/from_model.py +0 -0
  52. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/gears.py +0 -0
  53. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/holes.py +0 -0
  54. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/leaders.py +0 -0
  55. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/orchestrator.py +0 -0
  56. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/annotations/sections.py +0 -0
  57. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/audit.py +0 -0
  58. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/blend_contract.py +0 -0
  59. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/compose.py +0 -0
  60. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/document.py +0 -0
  61. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/document_evidence.py +0 -0
  62. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/document_input.py +0 -0
  63. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/evaluation/__init__.py +0 -0
  64. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/evaluation/step_analysis.py +0 -0
  65. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/export.py +0 -0
  66. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/feature_identity.py +0 -0
  67. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fits.py +0 -0
  68. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
  69. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
  70. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
  71. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
  72. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/fonts/__init__.py +0 -0
  73. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/inspection.py +0 -0
  74. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/intents.py +0 -0
  75. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/layout.py +0 -0
  76. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/_registry.py +0 -0
  77. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/angled_step_coverage.py +0 -0
  78. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/angular.py +0 -0
  79. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/blend_coverage.py +0 -0
  80. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/chamfer_coverage.py +0 -0
  81. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/channel_coverage.py +0 -0
  82. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/circular_blind_step_coverage.py +0 -0
  83. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/evidence.py +0 -0
  84. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/fillet_coverage.py +0 -0
  85. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/flat_coverage.py +0 -0
  86. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/gear_coverage.py +0 -0
  87. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/groove_coverage.py +0 -0
  88. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/hole_coverage.py +0 -0
  89. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/ink_overlap.py +0 -0
  90. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/issues.py +0 -0
  91. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/oriented_slot_coverage.py +0 -0
  92. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/pad_coverage.py +0 -0
  93. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/paired_ramp_step_coverage.py +0 -0
  94. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/passage_coverage.py +0 -0
  95. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/plate_coverage.py +0 -0
  96. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/pocket_coverage.py +0 -0
  97. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/pocket_pattern_coverage.py +0 -0
  98. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/polygonal_boss_coverage.py +0 -0
  99. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/polygonal_stock_coverage.py +0 -0
  100. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/prismatic_pocket_coverage.py +0 -0
  101. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
  102. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/rectangular_blind_slot_coverage.py +0 -0
  103. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/requirements.py +0 -0
  104. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/round_bottom_blind_slot_coverage.py +0 -0
  105. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/schedule_evidence.py +0 -0
  106. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/section_recess_coverage.py +0 -0
  107. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/slot_coverage.py +0 -0
  108. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/structural.py +0 -0
  109. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/suggest.py +0 -0
  110. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/through_step_coverage.py +0 -0
  111. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/linting/turned_step_coverage.py +0 -0
  112. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/location_contract.py +0 -0
  113. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/make_drawing.py +0 -0
  114. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/measurement_support.py +0 -0
  115. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/__init__.py +0 -0
  116. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/callout.py +0 -0
  117. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/compiled.py +0 -0
  118. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/declare.py +0 -0
  119. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/detect.py +0 -0
  120. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/ir.py +0 -0
  121. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/planner.py +0 -0
  122. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/model/pmi_lowering.py +0 -0
  123. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/oriented_slot_contract.py +0 -0
  124. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/plate_correspondence.py +0 -0
  125. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/profile_angles.py +0 -0
  126. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/progress.py +0 -0
  127. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/projection.py +0 -0
  128. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/py.typed +0 -0
  129. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recogniser_contract.py +0 -0
  130. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recogniser_policy.py +0 -0
  131. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recogniser_schema.py +0 -0
  132. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recognition/__init__.py +0 -0
  133. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recognition_cache.py +0 -0
  134. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recognition_frame.py +0 -0
  135. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/recognition_ownership.py +0 -0
  136. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/registry.py +0 -0
  137. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/repair.py +0 -0
  138. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/reporting.py +0 -0
  139. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/score.py +0 -0
  140. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/section_recess_contract.py +0 -0
  141. {draftwright-0.4.27 → draftwright-0.4.28}/src/draftwright/view_plan.py +0 -0
  142. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_evidence_contract.py +0 -0
  143. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_kernel.py +0 -0
  144. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_layout_sig.py +0 -0
  145. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_mutation_corpus.py +0 -0
  146. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_recogniser_public_contract.py +0 -0
  147. {draftwright-0.4.27 → draftwright-0.4.28}/tests/_section_recess_cases.py +0 -0
  148. {draftwright-0.4.27 → draftwright-0.4.28}/tests/conftest.py +0 -0
  149. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/ap242_single_cylinder_diameter.step +0 -0
  150. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/README.md +0 -0
  151. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
  152. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/blind-hole.step +0 -0
  153. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-asymmetric.step +0 -0
  154. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-compound.step +0 -0
  155. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-overlap.step +0 -0
  156. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-plain.step +0 -0
  157. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-planar-x.step +0 -0
  158. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-planar-y.step +0 -0
  159. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-planar-z.step +0 -0
  160. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-topology-a.step +0 -0
  161. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-topology-b.step +0 -0
  162. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/chamfer-turned.step +0 -0
  163. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-chamfers-v1.json +0 -0
  164. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-countersinks-v1.json +0 -0
  165. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-double-d-bores-v1.json +0 -0
  166. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-fillets-v1.json +0 -0
  167. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-flats-v1.json +0 -0
  168. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-grooves-v1.json +0 -0
  169. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-hole-patterns-v1.json +0 -0
  170. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-plates-v1.json +0 -0
  171. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-pocket-patterns-v1.json +0 -0
  172. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-pockets-v1.json +0 -0
  173. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-polygonal-bosses-v1.json +0 -0
  174. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-polygonal-stock-v1.json +0 -0
  175. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-rectangular-pads-v1.json +0 -0
  176. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-turned-steps-v1.json +0 -0
  177. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/corpus-v1.json +0 -0
  178. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-deburr.step +0 -0
  179. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-external-cone.step +0 -0
  180. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-mixed-pair.step +0 -0
  181. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-single.step +0 -0
  182. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-topology-a.step +0 -0
  183. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/countersink-topology-b.step +0 -0
  184. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-axis-x.step +0 -0
  185. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-axis-y.step +0 -0
  186. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-blind.step +0 -0
  187. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-coaxial-compound.step +0 -0
  188. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-opposed-blind.step +0 -0
  189. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-roll-30.step +0 -0
  190. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-round-bore.step +0 -0
  191. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-single-z.step +0 -0
  192. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-topology-a.step +0 -0
  193. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/double-d-topology-b.step +0 -0
  194. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-compound.step +0 -0
  195. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-overlap.step +0 -0
  196. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-plain.step +0 -0
  197. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-planar-x.step +0 -0
  198. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-planar-y.step +0 -0
  199. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-planar-z.step +0 -0
  200. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-repeated.step +0 -0
  201. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-topology-a.step +0 -0
  202. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-topology-b.step +0 -0
  203. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/fillet-turned.step +0 -0
  204. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-coaxial.step +0 -0
  205. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-double-d.step +0 -0
  206. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-lone-d.step +0 -0
  207. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-nonround.step +0 -0
  208. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-slanted-double-d.step +0 -0
  209. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-topology-a.step +0 -0
  210. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/flat-topology-b.step +0 -0
  211. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-compound.step +0 -0
  212. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-lone-x.step +0 -0
  213. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-lone-y.step +0 -0
  214. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-lone-z.step +0 -0
  215. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-monotonic-negative.step +0 -0
  216. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-narrow.step +0 -0
  217. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-topology-a.step +0 -0
  218. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/groove-topology-b.step +0 -0
  219. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-compound-equal.step +0 -0
  220. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-detached-body-negative.step +0 -0
  221. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-full-span-ledge-negative.step +0 -0
  222. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-nested-staircase-negative.step +0 -0
  223. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-topology-a.step +0 -0
  224. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-topology-b.step +0 -0
  225. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-x-negative.step +0 -0
  226. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-x-positive.step +0 -0
  227. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-y-negative.step +0 -0
  228. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-y-positive.step +0 -0
  229. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-z-negative.step +0 -0
  230. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pad-z-positive.step +0 -0
  231. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pattern-ambiguous.step +0 -0
  232. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pattern-grid.step +0 -0
  233. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pattern-topology-a.step +0 -0
  234. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pattern-topology-b.step +0 -0
  235. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plain-block.step +0 -0
  236. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-compound-equal.step +0 -0
  237. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-cross-topology-a.step +0 -0
  238. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-cross-topology-b.step +0 -0
  239. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-detached-negative.step +0 -0
  240. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-rotational-negative.step +0 -0
  241. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-single-negative.step +0 -0
  242. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-t-xz.step +0 -0
  243. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-t-yz.step +0 -0
  244. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-thick-negative.step +0 -0
  245. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-u-additive.step +0 -0
  246. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/plate-u-cut.step +0 -0
  247. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-compound.step +0 -0
  248. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-edge-anchored.step +0 -0
  249. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-lone.step +0 -0
  250. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-opposed.step +0 -0
  251. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-ambiguous.step +0 -0
  252. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-grid.step +0 -0
  253. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-linear.step +0 -0
  254. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-pair.step +0 -0
  255. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-topology-a.step +0 -0
  256. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-pattern-topology-b.step +0 -0
  257. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-prismatic-negative.step +0 -0
  258. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-side.step +0 -0
  259. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-through-negative.step +0 -0
  260. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-topology-a.step +0 -0
  261. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-topology-b.step +0 -0
  262. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/pocket-two-equal.step +0 -0
  263. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-compound-equal.step +0 -0
  264. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-detached-negative.step +0 -0
  265. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-in-plane-rotated.step +0 -0
  266. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-other-protrusions-negative.step +0 -0
  267. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-recess-negative.step +0 -0
  268. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-stock-negative.step +0 -0
  269. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-topology-a.step +0 -0
  270. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-topology-b.step +0 -0
  271. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-x.step +0 -0
  272. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-y.step +0 -0
  273. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-boss-z.step +0 -0
  274. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-compound-negative.step +0 -0
  275. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-cylinder-negative.step +0 -0
  276. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-irregular-negative.step +0 -0
  277. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-octagon-negative.step +0 -0
  278. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-recess-negative.step +0 -0
  279. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-roll17.step +0 -0
  280. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-topology-a.step +0 -0
  281. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-topology-b.step +0 -0
  282. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-translated.step +0 -0
  283. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-x.step +0 -0
  284. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/polygonal-stock-y.step +0 -0
  285. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/topology-a.step +0 -0
  286. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/topology-b.step +0 -0
  287. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-axis-x.step +0 -0
  288. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-axis-y.step +0 -0
  289. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-axis-z.step +0 -0
  290. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-compound.step +0 -0
  291. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-repeated-lengths.step +0 -0
  292. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-through-bore.step +0 -0
  293. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-topology-a.step +0 -0
  294. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-topology-b.step +0 -0
  295. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/evaluation/turned-step-translated-blind-bore.step +0 -0
  296. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
  297. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/grm03_thumbwheel_drive_screw_ap242_pmi.step +0 -0
  298. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/grm04_drive_plate.step +0 -0
  299. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
  300. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
  301. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/issue_1247_angled_blind_step.step +0 -0
  302. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
  303. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/issue_915_case_study_2.step +0 -0
  304. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
  305. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
  306. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
  307. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
  308. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
  309. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
  310. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
  311. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
  312. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
  313. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
  314. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
  315. {draftwright-0.4.27 → draftwright-0.4.28}/tests/fixtures/whistle_frame_reference.step +0 -0
  316. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/bracket_section.json +0 -0
  317. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/centered_rebate.json +0 -0
  318. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/chamfered.json +0 -0
  319. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/filleted.json +0 -0
  320. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/flange_dense.json +0 -0
  321. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/grid_plate.json +0 -0
  322. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/grooved_shaft.json +0 -0
  323. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/hex_bar.json +0 -0
  324. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/holed_slot.json +0 -0
  325. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/pocketed.json +0 -0
  326. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/prismatic_ladder.json +0 -0
  327. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/scattered_plate.json +0 -0
  328. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/side_drilled.json +0 -0
  329. {draftwright-0.4.27 → draftwright-0.4.28}/tests/refactor_golden/turned_stepped.json +0 -0
  330. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_add_dimension.py +0 -0
  331. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_adr0018_arrangement_gate.py +0 -0
  332. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_adr0018_view_routing.py +0 -0
  333. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_adr0018_view_selection.py +0 -0
  334. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_adr_corpus.py +0 -0
  335. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_agents_guide.py +0 -0
  336. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_api_docs.py +0 -0
  337. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_architecture_docs.py +0 -0
  338. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_audit_differential.py +0 -0
  339. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_balloon_ring_standoff.py +0 -0
  340. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_build_profile_harness.py +0 -0
  341. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_carve_free_position_callers.py +0 -0
  342. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_clone_budget.py +0 -0
  343. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_compiled_plan_boundary.py +0 -0
  344. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_counting_calls.py +0 -0
  345. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_declare.py +0 -0
  346. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_declared_recognition_gate.py +0 -0
  347. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_dense_sheet_canary.py +0 -0
  348. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_deprecation_dates.py +0 -0
  349. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_detect_once.py +0 -0
  350. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_detect_registry.py +0 -0
  351. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_dimension_role_vocabulary.py +0 -0
  352. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_drawing_encapsulation.py +0 -0
  353. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_e2e_slice.py +0 -0
  354. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_e2e_standards.py +0 -0
  355. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_export_dxf_curves.py +0 -0
  356. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_export_dxf_zoom.py +0 -0
  357. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_export_reproducible.py +0 -0
  358. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_external_recognition_boundary.py +0 -0
  359. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_fillets_adjacency.py +0 -0
  360. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_fits.py +0 -0
  361. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_flat_completeness.py +0 -0
  362. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_flat_stock_identity.py +0 -0
  363. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_flat_stock_opposition.py +0 -0
  364. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_gdt_placement.py +0 -0
  365. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_geometry_graph_spike.py +0 -0
  366. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_grid_lattice_convention.py +0 -0
  367. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_import_boundaries.py +0 -0
  368. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_iso_nts_caption_placement.py +0 -0
  369. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1000_envelope_reuse.py +0 -0
  370. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1006_measurement_comparison.py +0 -0
  371. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1058_wheel_profile.py +0 -0
  372. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1073_cross_body_patterns.py +0 -0
  373. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1082_polygonal_stock.py +0 -0
  374. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1086_declared_gears.py +0 -0
  375. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -0
  376. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1130_view_planning_evidence.py +0 -0
  377. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1142_hole_leader_labels.py +0 -0
  378. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1143_hole_completeness.py +0 -0
  379. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1144_transactional_hole_table.py +0 -0
  380. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1146_scale_completeness.py +0 -0
  381. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
  382. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
  383. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
  384. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1155_grm04_sheet_use.py +0 -0
  385. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1166_cross_pass_feature_leaders.py +0 -0
  386. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1176_quality_fidelity.py +0 -0
  387. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1177_angular_dimensions.py +0 -0
  388. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1187_unroutable_leaders.py +0 -0
  389. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1188_per_view_assignment.py +0 -0
  390. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1190_section_decision.py +0 -0
  391. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1196_deterministic_view_names.py +0 -0
  392. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1202_observed_drawing_consumer.py +0 -0
  393. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1204_multiscale_view_issues.py +0 -0
  394. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1209_linear_pmi_witnesses.py +0 -0
  395. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1215_envelope_tolerance.py +0 -0
  396. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +0 -0
  397. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1216_callout_reservation_measures_ink.py +0 -0
  398. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
  399. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1217_claimed_representations.py +0 -0
  400. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1219_location_claims_its_own_axis.py +0 -0
  401. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1229_ledger_member_keying.py +0 -0
  402. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
  403. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1245_passage_disposition.py +0 -0
  404. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1246_prismatic_pocket_disposition.py +0 -0
  405. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1247_angled_step_disposition.py +0 -0
  406. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1254_turned_chamfers.py +0 -0
  407. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1260_view_constraints.py +0 -0
  408. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1262_automatic_turned_views.py +0 -0
  409. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1276_turned_leader_targets.py +0 -0
  410. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1281_turned_fillets.py +0 -0
  411. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1299_page_escalation.py +0 -0
  412. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1308_machined_leader_analytics.py +0 -0
  413. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1312_engine_costs.py +0 -0
  414. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1325_nominal_agreement.py +0 -0
  415. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1332_overlap_remedy.py +0 -0
  416. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1332_zone_labels.py +0 -0
  417. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1333_bounded_ink_repair.py +0 -0
  418. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1334_prevent_ink.py +0 -0
  419. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1336_grm03_ap242_pmi_fixture.py +0 -0
  420. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1338_scale_before_page_escalation.py +0 -0
  421. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1349_precision_display.py +0 -0
  422. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1350_detected_takeover.py +0 -0
  423. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1351_structured_note_coverage.py +0 -0
  424. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1352_searchable_pdf_text.py +0 -0
  425. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1353_cnc_authoritative_workflow.py +0 -0
  426. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1357_framed_activation.py +0 -0
  427. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1357_framed_boundary.py +0 -0
  428. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1357_pmi_frame.py +0 -0
  429. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1360_thread_depth.py +0 -0
  430. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1369_hole_completeness_evidence.py +0 -0
  431. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1370_countersink_completeness_evidence.py +0 -0
  432. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1370_double_d_completeness_evidence.py +0 -0
  433. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1370_hole_pattern_completeness_evidence.py +0 -0
  434. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1371_flat_completeness_evidence.py +0 -0
  435. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1371_polygonal_stock_completeness_evidence.py +0 -0
  436. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1372_groove_completeness_evidence.py +0 -0
  437. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1372_pad_completeness_evidence.py +0 -0
  438. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1372_pocket_completeness_evidence.py +0 -0
  439. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1372_pocket_pattern_completeness_evidence.py +0 -0
  440. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1372_polygonal_boss_completeness_evidence.py +0 -0
  441. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1373_plate_completeness_evidence.py +0 -0
  442. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1374_chamfer_completeness_evidence.py +0 -0
  443. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1374_fillet_completeness_evidence.py +0 -0
  444. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1374_turned_step_completeness_evidence.py +0 -0
  445. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1378_diameter_leader_targets.py +0 -0
  446. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1382_046_step_inventory.py +0 -0
  447. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1382_circular_blind_step_semantics.py +0 -0
  448. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1382_framed_step_family_evidence.py +0 -0
  449. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1382_paired_ramp_semantics.py +0 -0
  450. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1382_through_step_semantics.py +0 -0
  451. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1390_sheet_registration.py +0 -0
  452. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1392_recognisers_048.py +0 -0
  453. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1395_degenerate_iso_region.py +0 -0
  454. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1396_layout_advisories.py +0 -0
  455. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1397_unverifiable_requirement_message.py +0 -0
  456. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1421_rectangular_blind_slot_completeness.py +0 -0
  457. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1421_rectangular_blind_slot_semantics.py +0 -0
  458. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1421_round_bottom_blind_slot_completeness.py +0 -0
  459. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1421_round_bottom_blind_slot_semantics.py +0 -0
  460. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1432_adoption.py +0 -0
  461. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1432_boundary_failures.py +0 -0
  462. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1432_oriented_slot_semantics.py +0 -0
  463. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1433_blend_semantics.py +0 -0
  464. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_boss_ownership.py +0 -0
  465. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_channel_ownership.py +0 -0
  466. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_cli_report_sidecar.py +0 -0
  467. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_generation_snapshot.py +0 -0
  468. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_nested_ownership.py +0 -0
  469. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_occurrence_ownership.py +0 -0
  470. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_pattern_ownership.py +0 -0
  471. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_plate_ownership.py +0 -0
  472. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_policy_dispositions.py +0 -0
  473. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_report_projection.py +0 -0
  474. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_report_writer.py +0 -0
  475. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_through_step_ownership.py +0 -0
  476. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1438_turned_step_ownership.py +0 -0
  477. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1450_boss_blend_ownership.py +0 -0
  478. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1460_step_inspection.py +0 -0
  479. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1466_dimension_options.py +0 -0
  480. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1466_semantic_sides.py +0 -0
  481. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1471_boundary_failures.py +0 -0
  482. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1471_evidence_schema.py +0 -0
  483. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1471_groove_profile.py +0 -0
  484. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1471_section_recess_contract.py +0 -0
  485. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1471_section_recess_pockets.py +0 -0
  486. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1479_radius_leader_targets.py +0 -0
  487. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1485_curved_pockets.py +0 -0
  488. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1485_quiddity_024_boundary.py +0 -0
  489. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1485_rounded_pockets.py +0 -0
  490. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1504_angle_patterns.py +0 -0
  491. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1504_angular_references.py +0 -0
  492. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1504_angular_rendering.py +0 -0
  493. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1504_canonical_angles.py +0 -0
  494. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1504_profile_angles.py +0 -0
  495. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1505_diameter_coverage.py +0 -0
  496. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1505_short_axial_chains.py +0 -0
  497. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1511_turned_boss_heights.py +0 -0
  498. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1514_projection_safeguard.py +0 -0
  499. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1515_first_angle.py +0 -0
  500. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1516_dimension_text.py +0 -0
  501. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1517_through_indicator.py +0 -0
  502. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1518_explicit_rear.py +0 -0
  503. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1524_tolerance_magnitude.py +0 -0
  504. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1530_section_provenance.py +0 -0
  505. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1531_semantic_hole_counts.py +0 -0
  506. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1532_authored_section_examples.py +0 -0
  507. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1533_review_diagnostics.py +0 -0
  508. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1534_build_progress.py +0 -0
  509. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1536_title_overflow.py +0 -0
  510. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_applicability.py +0 -0
  511. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_catalog.py +0 -0
  512. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_catalog_families.py +0 -0
  513. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_claim_authority.py +0 -0
  514. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_document.py +0 -0
  515. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_document_claims.py +0 -0
  516. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_document_coverage.py +0 -0
  517. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_document_report.py +0 -0
  518. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_report_authority.py +0 -0
  519. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1542_requirement_carriers.py +0 -0
  520. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1543_feature_schedules.py +0 -0
  521. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1543_schedule_requirements.py +0 -0
  522. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_1544_frame_document_canary.py +0 -0
  523. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_367_leader_ink.py +0 -0
  524. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_443_grm03_axial_coverage.py +0 -0
  525. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_563_placement_intent.py +0 -0
  526. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_676_polygonal_boss.py +0 -0
  527. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
  528. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_798_floor_cardinality.py +0 -0
  529. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_798_material_field.py +0 -0
  530. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_798_silhouette_lint.py +0 -0
  531. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_827_real_part_canary.py +0 -0
  532. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_883_location_identity.py +0 -0
  533. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_885_prismatic_coverage.py +0 -0
  534. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_909_sloped_profile.py +0 -0
  535. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_915_dense_case.py +0 -0
  536. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_916_pocket_leader.py +0 -0
  537. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_917_open_channel.py +0 -0
  538. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_924_zero_length_shoulders.py +0 -0
  539. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_955_height_contingency.py +0 -0
  540. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_issue_958_cross_solid_recognition.py +0 -0
  541. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_label_provenance.py +0 -0
  542. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_layout.py +0 -0
  543. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_layout_cleanliness.py +0 -0
  544. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_layout_hypothesis.py +0 -0
  545. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_layout_property.py +0 -0
  546. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_leader_footprint.py +0 -0
  547. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_lint_box_cache.py +0 -0
  548. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_lint_ink_overlap.py +0 -0
  549. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_lint_reconciliation.py +0 -0
  550. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_lint_structural.py +0 -0
  551. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_linting.py +0 -0
  552. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_location_vocabulary.py +0 -0
  553. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_note_verb.py +0 -0
  554. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_object_aspects.py +0 -0
  555. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_occupancy_boxes.py +0 -0
  556. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_overall_height_coverage.py +0 -0
  557. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_parameter_id.py +0 -0
  558. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_part_model.py +0 -0
  559. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pitch_dim_footprint.py +0 -0
  560. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pmi_datum_lowering.py +0 -0
  561. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pmi_gtol_lowering.py +0 -0
  562. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pmi_part21.py +0 -0
  563. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pocket_pattern.py +0 -0
  564. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_pocket_pattern_recognition.py +0 -0
  565. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_principal_profile_classifier.py +0 -0
  566. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_private_test_attr_reads.py +0 -0
  567. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_private_test_imports.py +0 -0
  568. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_projection_symbol_default.py +0 -0
  569. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_quality_components.py +0 -0
  570. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_recogniser_adoption.py +0 -0
  571. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_recogniser_contract.py +0 -0
  572. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_recognition_result.py +0 -0
  573. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_refactor_golden.py +0 -0
  574. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_registry.py +0 -0
  575. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_render_seam.py +0 -0
  576. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_repack_geometry_seam.py +0 -0
  577. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_score.py +0 -0
  578. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_script_detail_parity.py +0 -0
  579. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_shared_box_memo.py +0 -0
  580. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_gdt.py +0 -0
  581. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_identity_invariant.py +0 -0
  582. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_notes.py +0 -0
  583. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_of.py +0 -0
  584. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_section.py +0 -0
  585. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_sheet_tables.py +0 -0
  586. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_slanted_blind_step.py +0 -0
  587. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_slot_completeness.py +0 -0
  588. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_slot_pattern.py +0 -0
  589. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_slot_pattern_recognition.py +0 -0
  590. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_soft_deprecation.py +0 -0
  591. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_solve_trace.py +0 -0
  592. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_step_analysis_evaluation.py +0 -0
  593. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_strip_layout.py +0 -0
  594. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_suppression_ledger.py +0 -0
  595. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_suppression_marks.py +0 -0
  596. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_tolerances.py +0 -0
  597. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_turned_steps.py +0 -0
  598. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_version_bump_ci.py +0 -0
  599. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_view_plan.py +0 -0
  600. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_witness_label_reconciliation.py +0 -0
  601. {draftwright-0.4.27 → draftwright-0.4.28}/tests/test_workflows.py +0 -0
@@ -154,6 +154,21 @@
154
154
 
155
155
  ### Changed
156
156
 
157
+ - Updated the exact Quiddity runtime and declared-inspection contract to **0.2.8**, which stops
158
+ a modelled thread being read as a stack of turned shoulders and coalesces contiguous
159
+ equal-diameter bands into the one span they physically are. Measured on the repo corpus,
160
+ NIST CTC-05 is again the only fixture that moves: its ⌀304.8 region was three adjacent
161
+ rungs and is now one, in both STEP encodings (#1135, quiddity#587).
162
+
163
+ - Updated the exact Quiddity runtime and declared-inspection contract to **0.2.7**. Unlike the
164
+ 0.2.5 adoption below, this one changes drawings: the provider now requires circumferential
165
+ cylinder support to establish a turned-profile axis line, so rounded plate corners and parallel
166
+ offset cylinders no longer form a false stepped shaft. Measured on the repo corpus, NIST CTC-05
167
+ is the only fixture whose recognised turned profile moves — its two STEP encodings previously
168
+ disagreed (3 steps and 9 steps for the same solid) and now agree on 5 — and a plate part that
169
+ previously raised out of `generate_sheet_script` now emits and builds. No family, record schema
170
+ or adapter changed (#1555, quiddity#586).
171
+
157
172
  - Updated the exact Quiddity runtime and declared-inspection contract to 0.2.5 for the
158
173
  provider's recognition performance improvements.
159
174
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: draftwright
3
- Version: 0.4.27
3
+ Version: 0.4.28
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
@@ -692,7 +692,7 @@ Requires-Dist: numpy>=1.24
692
692
  Requires-Dist: ocp-gordon<0.3
693
693
  Requires-Dist: pillow>=10
694
694
  Requires-Dist: pypdfium2>=4
695
- Requires-Dist: quiddity==0.2.6
695
+ Requires-Dist: quiddity==0.2.8
696
696
  Requires-Dist: reportlab>=4.0
697
697
  Requires-Dist: rich>=10.11
698
698
  Requires-Dist: steputils==0.1
@@ -70,11 +70,24 @@ issue. The contract test derives package record outputs, converter registries, l
70
70
  and emitter branches independently, so copying a new name into the declaration alone cannot make CI
71
71
  pass.
72
72
 
73
- ### Quiddity 0.2.6 runtime contract
73
+ ### Quiddity 0.2.8 runtime contract
74
74
 
75
- The runtime pins the published `quiddity==0.2.6` package, following the 0.2.4 adoption in
75
+ The runtime pins the published `quiddity==0.2.8` package, following the 0.2.4 adoption in
76
76
  [#1486](https://github.com/pzfreo/draftwright/pull/1486) and the migration in
77
- [#1471](https://github.com/pzfreo/draftwright/issues/1471). Its public `quiddity`, `quiddity.evidence` and
77
+ [#1471](https://github.com/pzfreo/draftwright/issues/1471). 0.2.7 is a patch adoption: it requires
78
+ circumferential cylinder support to establish a turned-profile axis line, so rounded plate corners
79
+ and parallel offset cylinders no longer form a false stepped shaft
80
+ ([quiddity#586](https://github.com/pzfreo/quiddity/issues/586), [#1555](https://github.com/pzfreo/draftwright/issues/1555)).
81
+ No family, record schema or adapter changed.
82
+
83
+ 0.2.7 also partitions bands by physical axis line rather than by axis direction, requiring two
84
+ distinct diameters *per line*. One body can therefore publish **several** coaxial
85
+ `TurnedProfile`s where 0.2.6 published at most one. `Analysis.profiles` already holds every
86
+ body-local profile and is unaffected; `Analysis.prof` remains the compatible zero/one view and
87
+ is `None` for a plural result, which sends `holes.py`'s `a.prof is not None` branches down their
88
+ non-rotational path. **No fixture in this repository reaches plural cardinality on either
89
+ version**, so the green tiers are not evidence that path behaves well — it is newly reachable
90
+ and untested. Its public `quiddity`, `quiddity.evidence` and
78
91
  `quiddity.inspection` surfaces supply recognition, exact occurrence evidence and declared geometry
79
92
  reads. There is one recognition aggregate per build; consumers project that result rather than
80
93
  calling the document builder to obtain another run.
@@ -278,7 +278,7 @@ produces `angular_support_unverifiable`; contradictory supports produce
278
278
  `angular_support_mismatch`.
279
279
 
280
280
  Automatic drawings derive outside-profile angular requirements from ordered face
281
- supports in Quiddity 0.2.6. Angles already defined by a recognised chamfer or
281
+ supports, available since Quiddity 0.2.6. Angles already defined by a recognised chamfer or
282
282
  regular-polygon callout do not add duplicate automatic requirements. This requires
283
283
  the same run's exact face or shared-edge evidence, not matching numerical angles;
284
284
  explicit angle declarations remain available on those corners.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "draftwright"
7
- version = "0.4.27"
7
+ version = "0.4.28"
8
8
  description = "Automated technical-drawing generation for build123d"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -23,7 +23,7 @@ dependencies = [
23
23
  # published wheels, not only uv's development resolver constraints.
24
24
  "cadquery-ocp-novtk!=7.9.3.1.1 ; python_full_version >= '3.13'",
25
25
  "build123d-drafting-helpers>=0.15.1",
26
- "quiddity==0.2.6",
26
+ "quiddity==0.2.8",
27
27
  "numpy>=1.24",
28
28
  # PNG raster export (SVG→PDF→PNG). Both permissively licensed (Pillow HPND; pypdfium2
29
29
  # Apache-2.0 wrapping Google PDFium BSD-3) and ship pre-built wheels with NO native system
@@ -174,6 +174,15 @@ def _zone_divisions(page_w: float, page_h: float) -> tuple[int, int]:
174
174
 
175
175
  _TB_CLEAR = _MARGIN + 1.0 # title-block inset: one extra mm over _MARGIN for clearance
176
176
 
177
+ #: What the general-tolerance cell states when no tolerance was authored or sourced.
178
+ #: A blank cell is indistinguishable from an oversight and invites a shop to assume its
179
+ #: own house standard, so the absent case is named rather than left empty (#1157).
180
+ #: The cell is not tight — 48 mm on A4's 120 mm block, 60 mm above it, against 16.9 mm of
181
+ #: ink here — so this is a wording choice, not a width-forced one. The paired test still
182
+ #: measures it against the block's own `cell_bbox` on A4, the narrowest supported width,
183
+ #: because a longer replacement (a sentence, say) would overflow there and nowhere else.
184
+ _TOLERANCE_UNSPECIFIED = "UNSPECIFIED"
185
+
177
186
  _FONT_SIZE = 3.0 # annotation text height (page-mm); the draft preset is built with this
178
187
 
179
188
 
@@ -1236,7 +1245,12 @@ class Analysis:
1236
1245
  step_file: str | Path | Shape
1237
1246
  title: str
1238
1247
  number: str
1239
- tolerance: str
1248
+ #: The general tolerance for the title block. ``None`` means the caller supplied none
1249
+ #: and none was sourced — a distinct state from an explicitly authored string, because a
1250
+ #: general tolerance is a manufacturing requirement and defaulting one invents intent
1251
+ #: the source model may not carry (#1157). ``""`` is the explicit request for a blank
1252
+ #: cell. `_make_title_block` renders `None` as `_TOLERANCE_UNSPECIFIED`.
1253
+ tolerance: str | None
1240
1254
  drawn_by: str
1241
1255
  out: str
1242
1256
  # Canonical AP242 source census + extraction outcomes for a STEP input, including off mode
@@ -1351,7 +1365,7 @@ def _make_title_block(dwg, a: Analysis):
1351
1365
  so the two never drift."""
1352
1366
  title = _font_safe_text(a.title)
1353
1367
  number = _font_safe_text(a.number)
1354
- tolerance = _font_safe_text(a.tolerance)
1368
+ tolerance = _font_safe_text(_TOLERANCE_UNSPECIFIED if a.tolerance is None else a.tolerance)
1355
1369
  designed_by = _font_safe_text(_attribution_author(a.drawn_by))
1356
1370
  material = _font_safe_text(a.material)
1357
1371
  date = _font_safe_text(a.date)
@@ -771,6 +771,7 @@ def _analyse(
771
771
  scale=None,
772
772
  page=None,
773
773
  pmi=None,
774
+ source=None,
774
775
  model=None,
775
776
  decorations=None,
776
777
  authored=None,
@@ -933,12 +934,23 @@ def _analyse(
933
934
  # Semantic PMI census (AP242 only; separate read-only pass). Framed extraction receives
934
935
  # the provider frame before it classifies correlation topology, preserving tight local
935
936
  # boxes and arbitrary directions (#1401 / ADR 3 (was 0020)). Even off mode inventories a STEP
936
- # source so it can report ignored authored PMI; in-memory Shapes have no AP242 document.
937
- if not isinstance(step_file, Shape):
937
+ # source so it can report ignored authored PMI.
938
+ #
939
+ # An in-memory Shape has no AP242 document of its own, which used to end the matter — and
940
+ # a `Sheet` ALWAYS holds one, so no script-built drawing reconciled its PMI at all, not
941
+ # even to say it had not (#1563). `source` is the caller naming the STEP the solid was
942
+ # read from; a generated script already opens exactly that path in its own `part =
943
+ # import_step(...)` line, so the emitter can state it. It is the caller's claim, not a
944
+ # proof the bytes produced this solid, so `pmi_source` records name and digest and the
945
+ # stage summary reports them rather than leaving the link assumed.
946
+ pmi_source = None if isinstance(step_file, Shape) else step_file
947
+ if pmi_source is None and source is not None:
948
+ pmi_source = source
949
+ if pmi_source is not None:
938
950
  from draftwright.pmi import PmiExtractionReport, extract_pmi_report
939
951
 
940
952
  try:
941
- pmi_report = extract_pmi_report(step_file, frame=recognition_frame)
953
+ pmi_report = extract_pmi_report(pmi_source, frame=recognition_frame)
942
954
  if pmi_mode != "off":
943
955
  pmi_records = list(pmi_report.records)
944
956
  except Exception as exc:
@@ -75,7 +75,6 @@ from draftwright.linting.coverage import lint_axial_coverage
75
75
  from draftwright.model import (
76
76
  Datum,
77
77
  Feature,
78
- GrooveFeature,
79
78
  PartModel,
80
79
  StepFeature,
81
80
  build_pmi_features,
@@ -461,9 +460,7 @@ def _check_dimension_sources(model: PartModel) -> None:
461
460
  def _detect_part_model_analysis(part, *, pmi="off") -> tuple[PartModel, Analysis]:
462
461
  """Return one detected model together with the exact analysis run that produced it."""
463
462
 
464
- a = _analyse(
465
- part, title="", number="", tolerance="ISO 2768-m", drawn_by="", out="model", pmi=pmi
466
- )
463
+ a = _analyse(part, title="", number="", tolerance=None, drawn_by="", out="model", pmi=pmi)
467
464
  # `_analyse` already detected and stored the model, so calling `build_model(a)`
468
465
  # unconditionally re-ran every detector `build_part_model` doesn't take by injection —
469
466
  # the #602 duplicate-detection bug, fixed in `_assemble` but never here. It went unnoticed
@@ -567,62 +564,13 @@ def _assemble(
567
564
  # measurements actually reach the page is settled downstream and reported by lint
568
565
  # (`axial_length_missing`). Guard on the tiling condition rather than a classifier
569
566
  # proxy (is_rotational / prof both have blind spots).
570
- z_steps = [f for f in pm.features if isinstance(f, StepFeature) and f.frame.axis == "z"]
571
- # The global-envelope check is meaningful only in its legacy single-solid domain;
572
- # caller-owned group strings cannot turn one solid into several physical bodies.
573
- # Multiple solids can be parallel, axially disjoint, or accompanied by unrelated
574
- # compound members, so their steps need not tile the compound bbox (#1357).
575
- owns_global_envelope = any(feature.kind == "envelope" for feature in pm.features)
576
- if (
577
- z_steps
578
- and len(a.part.solids()) == 1
579
- and (pm.orientation == "z" or owns_global_envelope)
580
- ):
581
- tol = 1e-3 * max(a.z_size, 1.0) # small absolute float epsilon, floored
582
- # Tiling means the segments run end to end — a single reach to each end isn't
583
- # enough, since an interior gap is a stretch of part no declared step describes.
584
- # Walk the spans low→high, extending coverage.
585
- # A GROOVE counts as one of those segments (#953): it is machined INTO the turned
586
- # profile, so a shaft that has one is still a turned profile, which is the only
587
- # thing this guard is asking. Without it the emitted script for any grooved shaft
588
- # RAISED — the detector produces exactly this model (step, groove, step) and the
589
- # direct build draws it, so the engine rejected its own detector's output the
590
- # moment that output was declared rather than detected. Grooves are the only
591
- # detected feature that splits the chain: a chamfered or filleted shoulder leaves
592
- # the two step spans meeting (checked), and a bore or cross-hole carves no axial
593
- # interval. #631's own repro still raises.
594
- # What this does NOT do is verify the declaration against the solid, and it never
595
- # did: `.step(diameter=20, length=48, at=…)` fabricating one full-extent segment
596
- # already defeats it on its own, groove or no groove (checked). Declared spans are
597
- # the author's statement of intent, which ADR 4 (was 0011) takes at face value rather than
598
- # re-deriving, so this catches the honest mistake #631 reported — declaring the
599
- # boss you can see and getting a worse drawing — not a fabricated coverage claim.
600
- # Hardening it into a real verb-domain check is #956.
601
- # NOT claimed here: that the resulting drawing dimensions the height. On this very
602
- # fixture the step chain drops at placement (crowded shoulders) and the height,
603
- # suppressed at compile time on the premise the chain conveys it, is then conveyed
604
- # by nothing — identically on the detected path. That is a real defect, tracked
605
- # separately (#955); raising here would not fix it, only hide it from one of the
606
- # two front doors.
607
- spans = sorted(
608
- [(min(p0[2], p1[2]), max(p0[2], p1[2])) for f in z_steps for (p0, p1) in [f.span]]
609
- + [
610
- (f.frame.origin[2] - f.width / 2, f.frame.origin[2] + f.width / 2)
611
- for f in pm.features
612
- if isinstance(f, GrooveFeature) and f.frame.axis == "z"
613
- ]
614
- )
615
- covered = a.bb.min.Z
616
- for lo, hi in spans:
617
- if lo <= covered + tol:
618
- covered = max(covered, hi)
619
- if spans[0][0] > a.bb.min.Z + tol or covered < a.bb.max.Z - tol:
620
- raise ValueError(
621
- "step() declares a segment of a turned profile, but the declared steps "
622
- "don't span this part's full height — it is not a turned (rotational) "
623
- "body. For a boss (an external cylinder on a prismatic part) use .boss() "
624
- "— it renders its own ø and height."
625
- )
567
+ # The z-turned span check that used to RAISE here now reports from
568
+ # `linting.coverage.lint_turned_profile_span` instead (#1132). Raising made
569
+ # `generate_sheet_script` return nothing at all for a part whose recognised
570
+ # profile does not tile, and an entry point that produces no script and no
571
+ # drawing is the one failure a consumer cannot route around. The check itself is
572
+ # unchanged in substance; only its severity and its home moved, and the annotate
573
+ # pass's `reset_issues()` is why it cannot be recorded from here.
626
574
  # PMI (STEP AP242) is likewise detection-sourced, so a declared / emitted-script model
627
575
  # carries none. When PMI annotation is on, synthesise the same imported drafting
628
576
  # annotations detection would (render_pmi reads them off the model, gated on a.pmi_mode)
@@ -1175,7 +1123,7 @@ def _build_drawing_once(
1175
1123
  out: str | None = None,
1176
1124
  title: str | None = None,
1177
1125
  number: str = "DWG-001",
1178
- tolerance: str = "ISO 2768-m",
1126
+ tolerance: str | None = None,
1179
1127
  drawn_by: str = "",
1180
1128
  scale: float | None = None,
1181
1129
  page: str | tuple | None = None,
@@ -1211,6 +1159,12 @@ def _build_drawing_once(
1211
1159
  _required_tables=(),
1212
1160
  _select_automatic_views: bool = False,
1213
1161
  _document_input=None,
1162
+ *,
1163
+ #: The STEP document the geometry came from, when it is not `step_file` itself
1164
+ #: (#1563). Keyword-only: inserting it among the positional parameters would shift
1165
+ #: every later binding, which `test_existing_positional_arguments_keep_their_bindings`
1166
+ #: exists to catch — and did.
1167
+ source: str | Path | None = None,
1214
1168
  ) -> Drawing:
1215
1169
  """Build a customisable 4-view :class:`Drawing` without exporting it.
1216
1170
 
@@ -1326,6 +1280,7 @@ def _build_drawing_once(
1326
1280
  scale=scale,
1327
1281
  page=page,
1328
1282
  pmi=pmi,
1283
+ source=source,
1329
1284
  model=model,
1330
1285
  decorations=decorations,
1331
1286
  authored=authored,
@@ -1881,7 +1836,7 @@ def build_drawing(
1881
1836
  out: str | None = None,
1882
1837
  title: str | None = None,
1883
1838
  number: str = "DWG-001",
1884
- tolerance: str = "ISO 2768-m",
1839
+ tolerance: str | None = None,
1885
1840
  drawn_by: str = "",
1886
1841
  scale: float | None = None,
1887
1842
  page: str | tuple | None = None,
@@ -1915,6 +1870,11 @@ def build_drawing(
1915
1870
  _document_input=None,
1916
1871
  *,
1917
1872
  projection_symbol: bool = True,
1873
+ #: The STEP document the geometry came from, when it is not `step_file` itself
1874
+ #: (#1563). Keyword-only: inserting it among the positional parameters would shift
1875
+ #: every later binding, which `test_existing_positional_arguments_keep_their_bindings`
1876
+ #: exists to catch — and did.
1877
+ source: str | Path | None = None,
1918
1878
  ) -> Drawing:
1919
1879
  """Build a drawing, protecting required annotations under an explicit scale.
1920
1880
 
@@ -1954,6 +1914,7 @@ def build_drawing(
1954
1914
  auto_dims=auto_dims,
1955
1915
  detail_view=detail_view,
1956
1916
  pmi=pmi,
1917
+ source=source,
1957
1918
  repair=repair,
1958
1919
  assembly=assembly,
1959
1920
  model=model,
@@ -2839,7 +2800,7 @@ def make_drawing(
2839
2800
  out: str | None = None,
2840
2801
  title: str | None = None,
2841
2802
  number: str = "DWG-001",
2842
- tolerance: str = "ISO 2768-m",
2803
+ tolerance: str | None = None,
2843
2804
  drawn_by: str = "",
2844
2805
  scale: float | None = None,
2845
2806
  page: str | tuple | None = None,
@@ -2861,6 +2822,11 @@ def make_drawing(
2861
2822
  text_orientation: str = "aligned",
2862
2823
  *,
2863
2824
  projection_symbol: bool = True,
2825
+ #: The STEP document the geometry came from, when it is not `step_file` itself
2826
+ #: (#1563). Keyword-only: inserting it among the positional parameters would shift
2827
+ #: every later binding, which `test_existing_positional_arguments_keep_their_bindings`
2828
+ #: exists to catch — and did.
2829
+ source: str | Path | None = None,
2864
2830
  ) -> tuple[str, str]:
2865
2831
  """Generate a 4-view technical drawing from a STEP file or build123d object.
2866
2832
 
@@ -2871,7 +2837,10 @@ def make_drawing(
2871
2837
  when a build123d object is passed).
2872
2838
  title: Part title for the title block (default: stem uppercased).
2873
2839
  number: Drawing number (e.g. ``"DWG-042"``).
2874
- tolerance: General tolerance string (e.g. ``"ISO 2768-m"``).
2840
+ tolerance: General tolerance string (e.g. ``"ISO 2768-m"``). ``None`` (the
2841
+ default) states none: the title block says the tolerance is unspecified
2842
+ rather than inventing a manufacturing requirement the source never
2843
+ carried (#1157). ``""`` requests a blank cell.
2875
2844
  drawn_by: Designer name for the title block.
2876
2845
  scale: Drawing-scale override (e.g. ``5`` for 5:1, ``0.5`` for 1:2).
2877
2846
  Default: chosen automatically by :func:`choose_scale`.
@@ -2918,6 +2887,7 @@ def make_drawing(
2918
2887
  auto_dims=auto_dims,
2919
2888
  detail_view=detail_view,
2920
2889
  pmi=pmi,
2890
+ source=source,
2921
2891
  assembly=assembly,
2922
2892
  material=material,
2923
2893
  date=date,
@@ -159,7 +159,10 @@ def main(
159
159
  out: str | None = typer.Option(None, help="Output prefix (default: input stem)"),
160
160
  title: str | None = typer.Option(None, help="Part title for title block"),
161
161
  number: str = typer.Option("DWG-001", help="Drawing number"),
162
- tolerance: str = typer.Option("ISO 2768-m", help="General tolerance"),
162
+ tolerance: str | None = typer.Option(
163
+ None,
164
+ help="General tolerance (e.g. 'ISO 2768-m'); omitted, the title block says UNSPECIFIED",
165
+ ),
163
166
  drawn_by: str = typer.Option("", "--drawn-by", help="Designer name"),
164
167
  material: str = typer.Option("", help="Material for the title block"),
165
168
  date: str = typer.Option("", help="Date for the title block"),
@@ -125,6 +125,8 @@ from draftwright.linting import (
125
125
  lint_pmi_ignored,
126
126
  lint_pmi_lowering,
127
127
  lint_pmi_rendering,
128
+ lint_pmi_source_unknown,
129
+ lint_pmi_unreconciled,
128
130
  lint_pocket_coverage,
129
131
  lint_pocket_pattern_coverage,
130
132
  lint_polygonal_boss_coverage,
@@ -136,6 +138,7 @@ from draftwright.linting import (
136
138
  lint_round_bottom_blind_slot_coverage,
137
139
  lint_slot_coverage,
138
140
  lint_through_step_coverage,
141
+ lint_turned_profile_span,
139
142
  pmi_stage_summary,
140
143
  )
141
144
  from draftwright.linting.angular import lint_angular_supports, lint_profile_angle_coverage
@@ -210,6 +213,12 @@ _GEOMETRY_AWARE_CODES = frozenset(
210
213
  "unrecognised_defining_geometry",
211
214
  "pmi_not_lowered",
212
215
  "pmi_not_rendered",
216
+ # Registered here for the same reason as the two above: an unverified or
217
+ # fabricated AP242 claim is a statement about the geometry, not about layout
218
+ # (#1563). Leaving them out would let a drawing carrying either report
219
+ # `geometry_issues: 0`, which is the shape of defect this register exists for.
220
+ "pmi_unreconciled",
221
+ "pmi_source_unknown",
213
222
  # These REPLACE `pmi_not_rendered` for a record that produced no annotation (#1177);
214
223
  # the content is equally missing, so the count must not fall just because the
215
224
  # reason improved. `authored_dim_degenerate` suppressed that error without
@@ -219,6 +228,10 @@ _GEOMETRY_AWARE_CODES = frozenset(
219
228
  "authored_dim_degenerate",
220
229
  "authored_dim_source_unresolved",
221
230
  "axial_length_missing",
231
+ # A turned profile that leaves part of the body undescribed (#1132). Registered
232
+ # here for the same reason as `axial_length_missing` beside it: the shortfall is
233
+ # about the part, not about where an annotation landed.
234
+ "turned_profile_not_spanned",
222
235
  "flat_requirement_suppressed",
223
236
  "flat_requirement_missing",
224
237
  "flat_requirement_unverifiable",
@@ -4458,6 +4471,23 @@ class Drawing:
4458
4471
  cyls,
4459
4472
  recognition=recognition,
4460
4473
  )
4474
+ # Declared-vs-geometry in the axial direction (#1132): a z-turned profile that
4475
+ # leaves part of the body undescribed. Gated with the reconciliation check
4476
+ # above because both are only meaningful for a caller-declared model — the
4477
+ # detection path is NOT immune — it is scoped this way for a different reason.
4478
+ #
4479
+ # Measured on CADGenBench 132: a plain `build_drawing(<step file>)` detects
4480
+ # z-steps covering 0..113 of a 140 mm body and reports nothing here, while this
4481
+ # predicate applied to that same detected model returns the warning. Same part,
4482
+ # same shortfall, one door silent. It is scoped to the declared model because
4483
+ # that is where the raise it replaces lived, so this change alters no automatic
4484
+ # drawing. Widening it is a real question and a separate one.
4485
+ issues += lint_turned_profile_span(
4486
+ features,
4487
+ (self._analysis.bb.min.Z, self._analysis.bb.max.Z),
4488
+ orientation=getattr(self._part_model, "orientation", None),
4489
+ single_solid=len(self._analysis.part.solids()) == 1,
4490
+ )
4461
4491
  if physical and self._analysis is not None:
4462
4492
  issues += lint_pmi_ignored(
4463
4493
  self._analysis.pmi_report,
@@ -4477,6 +4507,20 @@ class Drawing:
4477
4507
  self._analysis.pmi_mode,
4478
4508
  decorations=getattr(self._part_model, "decorations", {}),
4479
4509
  )
4510
+ # The two directions the four checks above cannot cover, because each of them
4511
+ # reasons FROM the census: content whose census is missing entirely, and content
4512
+ # claiming an identity the census does not contain (#1563). Both take the report
4513
+ # itself rather than the mode — an absent census is the condition, not a setting.
4514
+ issues += lint_pmi_unreconciled(
4515
+ self._analysis.pmi_report,
4516
+ getattr(self._part_model, "features", ()),
4517
+ decorations=getattr(self._part_model, "decorations", {}),
4518
+ )
4519
+ issues += lint_pmi_source_unknown(
4520
+ self._analysis.pmi_report,
4521
+ getattr(self._part_model, "features", ()),
4522
+ decorations=getattr(self._part_model, "decorations", {}),
4523
+ )
4480
4524
  issues += list(self._registry.issues)
4481
4525
  # Attach a ready-to-paste fix snippet where one is computable (#29).
4482
4526
  # str | None — None when no concrete repair can be inferred.
@@ -17,7 +17,7 @@ from quiddity.inspection import inspection_api_manifest
17
17
  CONSUMER_INSPECTION_FORMAT = "draftwright-inspection-api"
18
18
  CONSUMER_INSPECTION_FORMAT_VERSION = 1
19
19
  SUPPORTED_INSPECTION_API_MAJOR = 1
20
- SUPPORTED_RECOGNISER_VERSION = "0.2.6"
20
+ SUPPORTED_RECOGNISER_VERSION = "0.2.8"
21
21
  _DISTRIBUTION = "quiddity"
22
22
  _PROVIDER_FORMAT = "quiddity-inspection-api"
23
23
  _NAMESPACE = "quiddity.inspection"
@@ -31,6 +31,7 @@ from draftwright.linting.coverage import (
31
31
  lint_location_coverage,
32
32
  lint_principal_profile_coverage,
33
33
  lint_prismatic_coverage,
34
+ lint_turned_profile_span,
34
35
  )
35
36
  from draftwright.linting.evidence import (
36
37
  ClaimOutcome,
@@ -53,6 +54,8 @@ from draftwright.linting.pmi_coverage import (
53
54
  lint_pmi_ignored,
54
55
  lint_pmi_lowering,
55
56
  lint_pmi_rendering,
57
+ lint_pmi_source_unknown,
58
+ lint_pmi_unreconciled,
56
59
  pmi_stage_summary,
57
60
  )
58
61
  from draftwright.linting.pocket_coverage import lint_pocket_coverage
@@ -97,6 +100,7 @@ __all__ = [
97
100
  "lint_circular_blind_step_coverage",
98
101
  "lint_chamfer_coverage",
99
102
  "lint_declaration_reconciliation",
103
+ "lint_turned_profile_span",
100
104
  "lint_drawing",
101
105
  "lint_feature_coverage",
102
106
  "lint_flat_coverage",
@@ -114,6 +118,8 @@ __all__ = [
114
118
  "lint_pmi_extraction",
115
119
  "lint_pmi_lowering",
116
120
  "lint_pmi_rendering",
121
+ "lint_pmi_source_unknown",
122
+ "lint_pmi_unreconciled",
117
123
  "pmi_stage_summary",
118
124
  "lint_principal_profile_coverage",
119
125
  "lint_profiled_bore_coverage",
@@ -2306,6 +2306,117 @@ def lint_boss_height_coverage(
2306
2306
  ]
2307
2307
 
2308
2308
 
2309
+ def lint_turned_profile_span(features, z_extent, *, orientation, single_solid) -> list:
2310
+ """Flag a z-turned profile whose declared steps leave part of the body undescribed (#1132).
2311
+
2312
+ This began as #631's verb-misuse diagnostic, raised from ``builder._assemble``: a caller
2313
+ reaching for ``.step()`` on a boss — an external cylinder on a prismatic part — declared a
2314
+ turned segment, which flipped the height ladder into turned-suppression and silently
2315
+ dropped the overall height. Raising made that visible.
2316
+
2317
+ Warning is sufficient because the symptom cannot co-occur with it:
2318
+ ``model/compiled.py::_compile_overall_height`` retains the overall-height rung whenever
2319
+ ``_step_chain_covers_extent(...)`` is false — the same tiling question, asked independently
2320
+ of the approved plan. Measured, ``dim_height`` is drawn on every part that trips this check
2321
+ and on none that declares its profile fully. So #631's dropped height is not what a warning
2322
+ now permits; it was already prevented elsewhere, and raising was belt and braces.
2323
+
2324
+ It stopped being only a hand-authoring mistake. ``generate_sheet_script`` settles its layout
2325
+ through the same path, so a part whose *recognised* profile does not tile produced no script
2326
+ and no drawing — and an entry point that returns nothing is the one failure a consumer
2327
+ cannot route around. A generated script is indistinguishable from hand-written code when it
2328
+ is re-run, so there is no provenance to branch on: the choice is raise for both or report for
2329
+ both, and reporting is what lets the drawing exist and say what it does not cover.
2330
+
2331
+ The two CADGenBench fixtures that still reach this carry profiles that are correct and
2332
+ merely partial — a threaded region on one, a 27 mm stretch on the other — since the false
2333
+ step sets behind the rest were fixed upstream (quiddity#586, #587).
2334
+
2335
+ Reported here rather than recorded during assembly because the annotate pass calls
2336
+ ``reset_issues()`` to keep a repack from duplicating drop records, which discards anything
2337
+ the builder recorded first. ``features`` is read duck-typed, like every check in this module.
2338
+ """
2339
+ if not single_solid:
2340
+ return []
2341
+
2342
+ def _axis(feature) -> str | None:
2343
+ # Duck-typed like the rest of this module, and defensive: a caller-supplied model may
2344
+ # carry a feature with no frame at all, and a lint check must not raise on one.
2345
+ return getattr(getattr(feature, "frame", None), "axis", None)
2346
+
2347
+ def _groove_band(feature) -> tuple[float, float] | None:
2348
+ # The same defensiveness as `_axis`, which a first pass applied to the step branch and
2349
+ # not to this one — leaving a groove with no `width` or no `origin` raising two lines
2350
+ # below the guard that was added. A lint check that crashes on a malformed model
2351
+ # reinstates the failure #1132 exists to remove.
2352
+ origin = getattr(getattr(feature, "frame", None), "origin", None)
2353
+ width = getattr(feature, "width", None)
2354
+ if origin is None or width is None or len(origin) < 3:
2355
+ return None
2356
+ return (origin[2] - width / 2, origin[2] + width / 2)
2357
+
2358
+ # A step with no usable span is skipped rather than guessed at: without endpoints its
2359
+ # extent is unknown, and inventing one would be worse than the silence. If that leaves no
2360
+ # steps at all the function returns below, reporting nothing — the honest outcome when
2361
+ # coverage is uncomputable, and the reason this filter is explicit rather than incidental.
2362
+ steps = [
2363
+ f
2364
+ for f in features
2365
+ if getattr(f, "kind", None) == "step" and _axis(f) == "z" and getattr(f, "span", None)
2366
+ ]
2367
+ if not steps:
2368
+ return []
2369
+ if orientation != "z" and not any(getattr(f, "kind", None) == "envelope" for f in features):
2370
+ return []
2371
+ lo_z, hi_z = z_extent
2372
+ tol = 1e-3 * max(hi_z - lo_z, 1.0)
2373
+ spans = sorted(
2374
+ [(min(a[2], b[2]), max(a[2], b[2])) for f in steps for (a, b) in [f.span]]
2375
+ + [
2376
+ band
2377
+ for f in features
2378
+ if getattr(f, "kind", None) == "groove" and _axis(f) == "z"
2379
+ for band in [_groove_band(f)]
2380
+ if band is not None
2381
+ ]
2382
+ )
2383
+ # Merge the spans, then report EVERY uncovered interval. A forward walk that stops at the
2384
+ # first gap misreports the rest: on CADGenBench 109 it stopped at 343.13 and named
2385
+ # `343.13..420`, while a declared step covers `366.82..420` — the real shortfall is 23.69 mm,
2386
+ # not 76.87. A diagnostic that overstates the gap is one nobody can act on.
2387
+ merged: list[list[float]] = []
2388
+ for lo, hi in spans:
2389
+ if merged and lo <= merged[-1][1] + tol:
2390
+ merged[-1][1] = max(merged[-1][1], hi)
2391
+ else:
2392
+ merged.append([lo, hi])
2393
+ uncovered = []
2394
+ cursor = lo_z
2395
+ for lo, hi in merged:
2396
+ if lo > cursor + tol:
2397
+ uncovered.append((cursor, lo))
2398
+ cursor = max(cursor, hi)
2399
+ if cursor < hi_z - tol:
2400
+ uncovered.append((cursor, hi_z))
2401
+ if not uncovered:
2402
+ return []
2403
+ where = ", ".join(f"{lo:g}..{hi:g}" for lo, hi in uncovered)
2404
+ total = sum(hi - lo for lo, hi in uncovered)
2405
+ return [
2406
+ LintIssue(
2407
+ severity="warning",
2408
+ code="turned_profile_not_spanned",
2409
+ message=(
2410
+ f"step() declares a segment of a turned profile, but the declared steps leave "
2411
+ f"{total:g} mm of this part's height undescribed ({where}). If these are bosses "
2412
+ "— external cylinders on a prismatic part — .boss() renders each with its own ø "
2413
+ "and height; if the profile is genuinely partial, the uncovered stretch is "
2414
+ "dimensioned by nothing."
2415
+ ),
2416
+ )
2417
+ ]
2418
+
2419
+
2309
2420
  def lint_declaration_reconciliation(features, cyls, *, recognition=None) -> list:
2310
2421
  """Flag a *declared* cylindrical feature with no matching geometry in the part (#487).
2311
2422