python-cad-tools 0.1.11__tar.gz → 0.1.16__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 (273) hide show
  1. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.github/workflows/ci.yml +62 -2
  2. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.github/workflows/downstream-compatibility.yml +6 -0
  3. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.github/workflows/release-candidate.yml +14 -0
  4. python_cad_tools-0.1.16/.github/workflows/release.yml +61 -0
  5. python_cad_tools-0.1.16/.opencode/tools/specrepo-autocommit.py +259 -0
  6. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/CHANGELOG.md +60 -0
  7. {python_cad_tools-0.1.11/src/python_cad_tools.egg-info → python_cad_tools-0.1.16}/PKG-INFO +7 -1
  8. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/README.md +6 -0
  9. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/neutral-model.md +107 -5
  10. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/project-configuration.md +14 -4
  11. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/public-api.md +3 -0
  12. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_project_loader.py +53 -1
  13. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/artifacts.py +20 -0
  14. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/build-info.json +1 -1
  15. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/cli.py +20 -2
  16. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/elements.py +5 -1
  17. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/ifc.py +187 -17
  18. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/manifests.py +23 -0
  19. python_cad_tools-0.1.16/src/python_cad_tools/recipes.py +293 -0
  20. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/validation.py +226 -5
  21. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16/src/python_cad_tools.egg-info}/PKG-INFO +7 -1
  22. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/SOURCES.txt +1 -0
  23. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/scm_file_list.json +2 -0
  24. python_cad_tools-0.1.16/src/python_cad_tools.egg-info/scm_version.json +8 -0
  25. python_cad_tools-0.1.11/.github/workflows/release.yml +0 -51
  26. python_cad_tools-0.1.11/.opencode/tools/specrepo-autocommit.py +0 -205
  27. python_cad_tools-0.1.11/src/python_cad_tools.egg-info/scm_version.json +0 -8
  28. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.gitattributes +0 -0
  29. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.githooks/pre-push +0 -0
  30. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.gitignore +0 -0
  31. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.opencode/commands/autocommit.md +0 -0
  32. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/.opencode/tools/specrepo-autocommit.js +0 -0
  33. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/AGENTS.md +0 -0
  34. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/CLAUDE.md +0 -0
  35. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/LICENSE +0 -0
  36. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/MANIFEST.in +0 -0
  37. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/build-semantics.md +0 -0
  38. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/drawing-extensions.md +0 -0
  39. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/manifests.md +0 -0
  40. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/spikes/format-feasibility.md +0 -0
  41. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/toolchain.md +0 -0
  42. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/two-tier-contract.md +0 -0
  43. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/docs/viewer-delivery.md +0 -0
  44. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/pyproject.toml +0 -0
  45. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/setup.cfg +0 -0
  46. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/__init__.py +0 -0
  47. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/__main__.py +0 -0
  48. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_locking.py +0 -0
  49. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_project_state.py +0 -0
  50. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_scaffold.py +0 -0
  51. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_transaction.py +0 -0
  52. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/app.webmanifest +0 -0
  53. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/asset-manifest.json +0 -0
  54. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/animationGroup-d5_0GqzW.js +0 -0
  55. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/bakedVertexAnimation-BTnhNnCG.js +0 -0
  56. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/basisTextureLoader-B1WedbgE.js +0 -0
  57. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/brdfTextureTools-DIdTXZSR.js +0 -0
  58. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/bumpFragment-C_S7LReC.js +0 -0
  59. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/bumpVertex-9p8w1w7z.js +0 -0
  60. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/bumpVertexDeclaration-B8rpdm3U.js +0 -0
  61. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/clipPlaneFragment-A-1cS0Wr.js +0 -0
  62. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/clipPlaneVertex-B34pEy_z.js +0 -0
  63. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/cubemapToSphericalPolynomial-BAw8ctMB.js +0 -0
  64. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/dds-BDxArwXs.js +0 -0
  65. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/dds.pure-D_Zw5OEt.js +0 -0
  66. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/ddsTextureLoader-DeQLZozV.js +0 -0
  67. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/default.fragment-BI3GAR2C.js +0 -0
  68. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/default.vertex-CQ4MILUZ.js +0 -0
  69. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/defaultUboDeclaration-DOBRS3iS.js +0 -0
  70. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/dumpTools-DCMMRWtL.js +0 -0
  71. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/envTextureLoader-C-7LpDe_.js +0 -0
  72. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/exrTextureLoader-oNqXrLmH.js +0 -0
  73. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphApplyForceBlock-DUMH2798.js +0 -0
  74. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphApplyImpulseBlock-DUvs7iqs.js +0 -0
  75. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphArrayIndexBlock-B-qeUHG6.js +0 -0
  76. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphBezierCurveEasingBlock-Cjm4_L1J.js +0 -0
  77. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphBinaryOperationBlock-CXnNy9QR.js +0 -0
  78. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphBranchBlock-DLUVB1dZ.js +0 -0
  79. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphCachedOperationBlock-BkfdjQtr.js +0 -0
  80. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphCancelDelayBlock-DwzbjNTQ.js +0 -0
  81. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphCodeExecutionBlock-CzFaSgik.js +0 -0
  82. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphConditionalDataBlock-DsMUDoGH.js +0 -0
  83. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphConsoleLogBlock-CVWywmBY.js +0 -0
  84. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphConstantBlock-BNIgu4QC.js +0 -0
  85. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphContextBlock-DuQCYIgK.js +0 -0
  86. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphCounterBlock-DxCqjQc8.js +0 -0
  87. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphDataSwitchBlock-BOncXvGP.js +0 -0
  88. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphDebounceBlock-43eNp_3W.js +0 -0
  89. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphDebugBlock-CYRuaSbJ.js +0 -0
  90. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphDoNBlock-Du-7uIwS.js +0 -0
  91. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphEasingBlock-C6lQQb9c.js +0 -0
  92. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphFlipFlopBlock-Ba-WebLx.js +0 -0
  93. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphForLoopBlock-CC4ZykmE.js +0 -0
  94. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphFunctionReferenceBlock-Cc8odCYm.js +0 -0
  95. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGLTFDataProvider-Bs8eI-tc.js +0 -0
  96. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetAngularVelocityBlock-BR2ioMLJ.js +0 -0
  97. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetAssetBlock-DD4Eo4N8.js +0 -0
  98. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetLinearVelocityBlock-CiXY_22u.js +0 -0
  99. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetPhysicsMassPropertiesBlock-BFuYrykd.js +0 -0
  100. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetPropertyBlock-yylHk0Tj.js +0 -0
  101. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetSoundVolumeBlock-Yoy3NMR4.js +0 -0
  102. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphGetVariableBlock-DP0lG6uk.js +0 -0
  103. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphIndexOfBlock-Dp46lAXL.js +0 -0
  104. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphInterpolationBlock-DAAojSot.js +0 -0
  105. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphIsKeyPressedBlock-BzyaFJtY.js +0 -0
  106. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphIsSoundPlayingBlock-4qIsPViO.js +0 -0
  107. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphJsonPointerParserBlock-BZG5ehwx.js +0 -0
  108. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphKeyDownEventBlock-rpKm7KQS.js +0 -0
  109. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphKeyUpEventBlock-DZ0cYho3.js +0 -0
  110. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphKeyboardEventBlock-CiAmYMbH.js +0 -0
  111. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphMathBlocks-CbJDlFUY.js +0 -0
  112. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphMathCombineExtractBlocks-DICrYBP4.js +0 -0
  113. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphMatrixMathBlocks-ftOIDo5d.js +0 -0
  114. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphMeshPickEventBlock-DTChczhf.js +0 -0
  115. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphMultiGateBlock-DdupWV9J.js +0 -0
  116. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPauseAnimationBlock-DBsgO-6v.js +0 -0
  117. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPauseSoundBlock-DWcr1ULl.js +0 -0
  118. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPhysicsCollisionEventBlock-CVKDMyoo.js +0 -0
  119. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPlayAnimationBlock-BXVH0aEG.js +0 -0
  120. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPlaySoundBlock-LNU38ZaS.js +0 -0
  121. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPointerDownEventBlock-L9Wzp4sm.js +0 -0
  122. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPointerMoveEventBlock-Cgf9rHw2.js +0 -0
  123. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPointerOutEventBlock-0bOFbyCB.js +0 -0
  124. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPointerOverEventBlock-CJQEfL96.js +0 -0
  125. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphPointerUpEventBlock-Dr4yXdtL.js +0 -0
  126. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphReceiveCustomEventBlock-DpKjQPwo.js +0 -0
  127. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSceneReadyEventBlock-CTK4Ndci.js +0 -0
  128. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSceneTickEventBlock-CzJbobbg.js +0 -0
  129. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSendCustomEventBlock-DBQ1n5eJ.js +0 -0
  130. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSequenceBlock-oBhLC7Vj.js +0 -0
  131. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetAngularVelocityBlock-DXlS3umF.js +0 -0
  132. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetDelayBlock-DhrCI14Z.js +0 -0
  133. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetLinearVelocityBlock-DdNE9BcN.js +0 -0
  134. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetPhysicsMotionTypeBlock-Be7qTZ0l.js +0 -0
  135. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetPropertyBlock-Bx8fCC87.js +0 -0
  136. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetSoundVolumeBlock-Bmh5show.js +0 -0
  137. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSetVariableBlock-BP87cysh.js +0 -0
  138. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSoundEndedEventBlock-DPK4HFJ5.js +0 -0
  139. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphStopAnimationBlock-9n5l3RYF.js +0 -0
  140. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphStopSoundBlock-BkqUQ3IX.js +0 -0
  141. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphSwitchBlock-CzYmr0Rg.js +0 -0
  142. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphThrottleBlock-C72DA8Ot.js +0 -0
  143. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphTransformCoordinatesSystemBlock-B57atF6V.js +0 -0
  144. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphTypeToTypeBlocks-BwO8ctcl.js +0 -0
  145. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphUnaryOperationBlock-B5xQ7raL.js +0 -0
  146. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphVectorMathBlocks-BSQ0Jp6s.js +0 -0
  147. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphWaitAllBlock-DkjMKncY.js +0 -0
  148. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/flowGraphWhileLoopBlock-DiDLbXDS.js +0 -0
  149. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/fogFragment-QU9YOYuH.js +0 -0
  150. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting-CBvJqSQF.js +0 -0
  151. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting-EGwqbpHv.js +0 -0
  152. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting.fragment-CG3O4l2t.js +0 -0
  153. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting.fragment-CYV0OcvY.js +0 -0
  154. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting.vertex-DU77eH5y.js +0 -0
  155. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplatting.vertex-s8IsAoDR.js +0 -0
  156. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplattingVoxel.fragment-Bt1AWZNn.js +0 -0
  157. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplattingVoxel.fragment-luoOzTyP.js +0 -0
  158. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplattingVoxel.vertex-m9aQdgcg.js +0 -0
  159. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/gaussianSplattingVoxel.vertex-xDMDxXMl.js +0 -0
  160. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/geometry.fragment-C_-6JJr4.js +0 -0
  161. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/geometry.fragment-oisMFtj8.js +0 -0
  162. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/geometry.vertex-CBkXTBVF.js +0 -0
  163. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/geometry.vertex-DQDqvDk5.js +0 -0
  164. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/glowBlurPostProcess.fragment-QolNMgw6.js +0 -0
  165. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/glowMapGeneration.fragment-DRwn6uC2.js +0 -0
  166. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/glowMapGeneration.vertex-BPPwu0E9.js +0 -0
  167. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/glowMapMerge.fragment-ODjisfEL.js +0 -0
  168. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/glowMapMerge.vertex-DB7eIwXj.js +0 -0
  169. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/harmonicsFunctions-B2jlXPLE.js +0 -0
  170. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/hdrTextureLoader-BGQvgh0h.js +0 -0
  171. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/helperFunctions-B6Z1LJrO.js +0 -0
  172. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/iesTextureLoader-8wFKF-ak.js +0 -0
  173. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/index-BnAaL7KS.js +0 -0
  174. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/index-CnrKUEff.css +0 -0
  175. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlur.fragment-C0PAazdd.js +0 -0
  176. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlur.fragment-DmepFK-C.js +0 -0
  177. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlur.vertex-CQTyg7d5.js +0 -0
  178. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlur.vertex-C_mnrqaY.js +0 -0
  179. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlurVaryingDeclaration-DCLBcYIA.js +0 -0
  180. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/kernelBlurVaryingDeclaration-DuoJgAZp.js +0 -0
  181. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/ktxTextureLoader-CIypOERT.js +0 -0
  182. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/lightFragment-BinX63GB.js +0 -0
  183. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/logDepthDeclaration-D8jcsZiW.js +0 -0
  184. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/logDepthVertex-CAoFmcco.js +0 -0
  185. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/mainUVVaryingDeclaration-oF31v9Zp.js +0 -0
  186. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/mesh.vertexData.functions-ayNlGC5K.js +0 -0
  187. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/meshUboDeclaration-BXrkHWWW.js +0 -0
  188. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/oitFragment-2x3JPdq6.js +0 -0
  189. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbr.fragment-B5ZDpeFy.js +0 -0
  190. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbr.fragment-CpT08ThE.js +0 -0
  191. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbr.vertex-BaGhkjmV.js +0 -0
  192. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbr.vertex-DAeXubyL.js +0 -0
  193. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrMaterial.pure-BXY_lClt.js +0 -0
  194. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrMaterialLoadingAdapter-MpirTHMd.js +0 -0
  195. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrTransmissionLayerData-CHHhh58w.js +0 -0
  196. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrTransmissionLayerData-DthxrR9-.js +0 -0
  197. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrUboDeclaration--Zhq0q7d.js +0 -0
  198. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/openpbrUboDeclaration-CXcZlREH.js +0 -0
  199. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/packingFunctions-Bo_ikKLB.js +0 -0
  200. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/packingFunctions-u3uWRkpF.js +0 -0
  201. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pass.fragment-slK02MnO.js +0 -0
  202. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/passCube.fragment-C13WHRV7.js +0 -0
  203. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/passCube.fragment-DnuA3v4l.js +0 -0
  204. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbr.fragment-8v2GDfO1.js +0 -0
  205. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbr.vertex-BuCPFkDX.js +0 -0
  206. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrBRDFFunctions-5nHUuKRr.js +0 -0
  207. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrDebug-C8fLVEpD.js +0 -0
  208. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrIBLFunctions-BM49sbQB.js +0 -0
  209. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrMaterial.pure-B6n6Ic80.js +0 -0
  210. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrMaterialLoadingAdapter-C0d04FRz.js +0 -0
  211. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/pbrUboDeclaration-CL7R5LTR.js +0 -0
  212. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/postprocess.vertex-BhCyZbyQ.js +0 -0
  213. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/procedural.vertex-Cb5DsSFx.js +0 -0
  214. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/procedural.vertex-W-IcNTXE.js +0 -0
  215. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/reflectionFunction-DYrae64q.js +0 -0
  216. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/rgbdDecode.fragment-CFpIpdxk.js +0 -0
  217. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/rgbdEncode.fragment-BIBfrJET.js +0 -0
  218. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/rgbdEncode.fragment-yPbrkGKz.js +0 -0
  219. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/sceneUboDeclaration-D5YHSknt.js +0 -0
  220. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/textureProcessor.fragment-GSzJSZKX.js +0 -0
  221. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/textureProcessor.fragment-NwUMt_sy.js +0 -0
  222. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/tgaTextureLoader-Z9HWdnv1.js +0 -0
  223. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/assets/vertexColorMixing-DkZl_JUT.js +0 -0
  224. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/favicon.svg +0 -0
  225. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/index.html +0 -0
  226. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/_viewer_static/sw.js +0 -0
  227. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/build.py +0 -0
  228. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/context.py +0 -0
  229. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/determinism.py +0 -0
  230. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/drawings/__init__.py +0 -0
  231. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/drawings/_catalog.py +0 -0
  232. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/drawings/_validation.py +0 -0
  233. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exceptions.py +0 -0
  234. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/__init__.py +0 -0
  235. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/base.py +0 -0
  236. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/__init__.py +0 -0
  237. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/annotations.py +0 -0
  238. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/dxf.py +0 -0
  239. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/model.py +0 -0
  240. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/pdf.py +0 -0
  241. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/primitives.py +0 -0
  242. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/projection.py +0 -0
  243. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/drawings/svg.py +0 -0
  244. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/glb.py +0 -0
  245. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/quantities.py +0 -0
  246. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/exporters/step.py +0 -0
  247. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/geometry.py +0 -0
  248. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/project_config.py +0 -0
  249. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/py.typed +0 -0
  250. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/runtime_sync.py +0 -0
  251. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/build-manifest-1.json +0 -0
  252. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/design-manifest-1.json +0 -0
  253. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/download-manifest-2.json +0 -0
  254. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/drawing-annotations-1.json +0 -0
  255. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/glb-manifest-1.json +0 -0
  256. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/ifc-validation-1.json +0 -0
  257. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/quantities-1.json +0 -0
  258. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/run-metadata-1.json +0 -0
  259. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/site-metadata-1.json +0 -0
  260. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/schemas/step-validation-1.json +0 -0
  261. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/site.py +0 -0
  262. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/.gitignore +0 -0
  263. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/README.md +0 -0
  264. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/config.py +0 -0
  265. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/drawing_annotations.py +0 -0
  266. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/generated/.gitkeep +0 -0
  267. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/model.py +0 -0
  268. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/templates/project/pyproject.toml +0 -0
  269. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools/units.py +0 -0
  270. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/dependency_links.txt +0 -0
  271. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/entry_points.txt +0 -0
  272. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/requires.txt +0 -0
  273. {python_cad_tools-0.1.11 → python_cad_tools-0.1.16}/src/python_cad_tools.egg-info/top_level.txt +0 -0
@@ -1,3 +1,22 @@
1
+ # Main CI workflow: runs the full test/quality/packaging suite on
2
+ # every PR and on push to main, and is also the ONE place that
3
+ # publishes to PyPI.
4
+ #
5
+ # Publishing happens only in the `build-publish` job, gated behind
6
+ # every other job via `needs:` and only when the ref being tested is
7
+ # a "v*" tag (see the `if:` on that job). release.yml creates that
8
+ # tag but pushes it using the default GITHUB_TOKEN, and GitHub does
9
+ # not start new workflow runs from GITHUB_TOKEN-authored pushes (its
10
+ # anti-recursion rule) — so the tag push alone won't reach this file.
11
+ # Instead release.yml explicitly dispatches this workflow against the
12
+ # new tag via `workflow_dispatch` below, which IS exempt from that
13
+ # rule. `workflow_dispatch` is included here for that purpose (and
14
+ # lets you manually re-run CI against any existing tag/ref by hand).
15
+ #
16
+ # release.yml itself does not build or publish anything — it only
17
+ # creates the tag and triggers this run. Keeping publish logic in one
18
+ # gated place (instead of duplicating it in release.yml) avoids two
19
+ # workflows racing to publish the same version.
1
20
  name: CI
2
21
 
3
22
  on:
@@ -5,11 +24,14 @@ on:
5
24
  branches: [main]
6
25
  tags: ['v*']
7
26
  pull_request:
27
+ workflow_dispatch:
8
28
 
9
29
  permissions:
10
30
  contents: read
11
31
 
12
32
  jobs:
33
+ # Fastest signal: static checks plus unit/typing tests, so obvious
34
+ # problems fail before the slower jobs below even start.
13
35
  lint-type-unit:
14
36
  name: Lint, type, unit
15
37
  runs-on: ubuntu-latest
@@ -25,6 +47,8 @@ jobs:
25
47
  - run: mypy
26
48
  - run: pytest tests/unit tests/typing -q
27
49
 
50
+ # Integration tests against the real CAD/BIM/mesh/drawing exporter
51
+ # libraries (not mocked) to catch toolchain-level breakage.
28
52
  exporter-integration:
29
53
  name: Exporter integration
30
54
  runs-on: ubuntu-latest
@@ -38,6 +62,8 @@ jobs:
38
62
  - run: pip install -e '.[dev]'
39
63
  - run: pytest tests/integration -q
40
64
 
65
+ # Builds the TypeScript viewer and runs its unit + headless-browser
66
+ # (Playwright) end-to-end tests.
41
67
  viewer-browser:
42
68
  name: Viewer and browser tests
43
69
  runs-on: ubuntu-latest
@@ -65,6 +91,9 @@ jobs:
65
91
  - working-directory: viewer
66
92
  run: npm run test:e2e
67
93
 
94
+ # Builds the wheel and sdist, validates them with twine, and runs
95
+ # packaging-specific tests — catches issues the editable install
96
+ # used elsewhere in CI wouldn't surface.
68
97
  wheel-sdist:
69
98
  name: Wheel and sdist inspection
70
99
  runs-on: ubuntu-latest
@@ -80,6 +109,9 @@ jobs:
80
109
  - run: python -m twine check dist/*
81
110
  - run: pytest tests/packaging -q
82
111
 
112
+ # Installs the built wheel into a fresh venv (non-editable, unlike
113
+ # the rest of CI) and runs a generic project through the CLI —
114
+ # catches packaging omissions an editable install would hide.
83
115
  clean-install:
84
116
  name: Clean non-editable install
85
117
  runs-on: ubuntu-latest
@@ -104,6 +136,8 @@ jobs:
104
136
  /tmp/clean-venv/bin/python-cad build --project-root /tmp/generic-project
105
137
  /tmp/clean-venv/bin/python-cad verify --project-root /tmp/generic-project
106
138
 
139
+ # End-to-end CLI smoke test on an editable install: init, build,
140
+ # verify, clean.
107
141
  generic-e2e:
108
142
  name: Generic E2E
109
143
  runs-on: ubuntu-latest
@@ -122,6 +156,7 @@ jobs:
122
156
  python-cad verify --project-root /tmp/e2e-project
123
157
  python-cad clean --project-root /tmp/e2e-project
124
158
 
159
+ # Guards against unintentional breaking changes to the public API.
125
160
  public-api:
126
161
  name: Public API surface
127
162
  runs-on: ubuntu-latest
@@ -135,6 +170,8 @@ jobs:
135
170
  - run: pip install -e '.[dev]'
136
171
  - run: pytest tests/unit/test_public_api.py -q
137
172
 
173
+ # Fails if legacy/retired naming from a prior repo migration
174
+ # reappears in tracked source (see EXCLUDES below for what's exempt).
138
175
  active-terminology:
139
176
  name: Active terminology scan
140
177
  runs-on: ubuntu-latest
@@ -157,6 +194,9 @@ jobs:
157
194
  fi
158
195
  echo "No active legacy concepts found."
159
196
 
197
+ # Enforces repository layout policy: legacy files/dirs stay absent,
198
+ # required symlinks (CLAUDE.md -> AGENTS.md) exist, backups stay
199
+ # untracked, and the expected workflow files are present.
160
200
  tree-shape:
161
201
  name: Tree shape and policy checks
162
202
  runs-on: ubuntu-latest
@@ -187,6 +227,9 @@ jobs:
187
227
  done
188
228
  echo "All tree shape checks passed."
189
229
 
230
+ # Confirms init/build works on Linux, macOS, and Windows. Windows
231
+ # skips ruff/mypy since static checks aren't part of the
232
+ # cross-platform contract, just the CLI behavior.
190
233
  supported-platforms:
191
234
  name: Supported platforms (${{ matrix.os }})
192
235
  strategy:
@@ -218,6 +261,9 @@ jobs:
218
261
  python-cad build --project-root C:\platform-test
219
262
  if: matrix.os == 'windows-latest'
220
263
 
264
+ # Generates a per-OS `pip freeze` lockfile as a downloadable
265
+ # artifact for reference. Informational only — not enforced or
266
+ # committed anywhere automatically.
221
267
  platform-locks:
222
268
  name: Platform lock generation (${{ matrix.os }})
223
269
  strategy:
@@ -250,6 +296,10 @@ jobs:
250
296
  name: ${{ matrix.lock }}
251
297
  path: ${{ matrix.lock }}
252
298
 
299
+ # Confirms every optional dependency group (cad, bim, mesh, ...)
300
+ # installs cleanly and imports across OS/Python combinations. PRs
301
+ # only run a fast subset (core+all on ubuntu/py3.13) via the gate
302
+ # step below; main and tag pushes run the full matrix.
253
303
  toolchain-matrix:
254
304
  name: Toolchain matrix (${{ matrix.os }}, py${{ matrix.python }}, ${{ matrix.group }})
255
305
  strategy:
@@ -368,9 +418,17 @@ jobs:
368
418
  name: toolchain-compatibility-${{ matrix.os }}-py${{ matrix.python }}-${{ matrix.group }}
369
419
  path: toolchain-compatibility.json
370
420
 
421
+ # THE publish step for this repo — only runs when the ref under
422
+ # test is a "v*" tag, and only after every job above has passed
423
+ # (see `needs:`). Checking the ref rather than the event name lets
424
+ # this fire both from a direct tag push and from release.yml's
425
+ # workflow_dispatch trigger (see the file header for why dispatch
426
+ # is needed). Tags are created by the separate "Release" workflow
427
+ # (release.yml); nothing else in this repo should build or publish
428
+ # to PyPI.
371
429
  build-publish:
372
430
  name: Build and publish to PyPI
373
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
431
+ if: startsWith(github.ref, 'refs/tags/v')
374
432
  needs:
375
433
  - lint-type-unit
376
434
  - exporter-integration
@@ -412,9 +470,11 @@ jobs:
412
470
  TWINE_USERNAME: __token__
413
471
  TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
414
472
 
473
+ # Generates a SLSA build provenance attestation for the artifacts
474
+ # build-publish just uploaded, for supply-chain verifiability.
415
475
  provenance:
416
476
  name: Generate SLSA provenance
417
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
477
+ if: startsWith(github.ref, 'refs/tags/v')
418
478
  needs: [build-publish]
419
479
  permissions:
420
480
  actions: read
@@ -1,3 +1,9 @@
1
+ # Placeholder for testing python-cad-tools wheels against a future
2
+ # downstream "companion repository" (not yet created). It intentionally
3
+ # always fails (exit 1) — that's not a bug, it's a guard against this
4
+ # check silently being treated as passing before it's actually
5
+ # implemented. Do not run it or remove the exit 1 until a companion
6
+ # repository exists at the URL you'd pass in.
1
7
  name: Downstream compatibility
2
8
 
3
9
  on:
@@ -1,3 +1,11 @@
1
+ # Release candidate: builds and verifies a pre-release artifact for
2
+ # manual QA WITHOUT publishing anything to PyPI or pushing any tag.
3
+ # Use this to sanity-check a wheel/sdist before running the real
4
+ # "Release" workflow (release.yml), which does publish.
5
+ #
6
+ # To run: Actions -> Release candidate -> Run workflow, with a label
7
+ # for this candidate (e.g. "0.1.0rc1"). Download the built artifact
8
+ # from the "build" job's summary page to test it locally.
1
9
  name: Release candidate
2
10
 
3
11
  on:
@@ -12,6 +20,9 @@ permissions:
12
20
  contents: read
13
21
 
14
22
  jobs:
23
+ # Builds the wheel/sdist after lint/type/unit checks pass, and
24
+ # uploads them as a workflow artifact (90-day retention). Nothing
25
+ # is published here.
15
26
  build:
16
27
  name: Build wheel and sdist
17
28
  runs-on: ubuntu-latest
@@ -54,6 +65,9 @@ jobs:
54
65
  path: dist/
55
66
  retention-days: 90
56
67
 
68
+ # Re-downloads the build job's artifact, re-verifies its hashes, and
69
+ # installs it non-editably — catches artifact corruption or a
70
+ # mismatch between what "build" produced and what got uploaded.
57
71
  verify:
58
72
  name: Verify candidate hashes
59
73
  runs-on: ubuntu-latest
@@ -0,0 +1,61 @@
1
+ # Release: cuts a new version by tagging `main`. Manual trigger only.
2
+ #
3
+ # This workflow does NOT build or publish anything itself — it only
4
+ # creates a "v*" tag and hands off to ci.yml's `build-publish` job,
5
+ # which is the single, test-gated path to PyPI. Keeping build/publish
6
+ # out of this file avoids two workflows racing to publish the same
7
+ # version.
8
+ #
9
+ # The hand-off can't just be "push the tag": pushes made with the
10
+ # default GITHUB_TOKEN (used below via actions/checkout) don't start
11
+ # other workflow runs — that's a deliberate GitHub anti-recursion
12
+ # rule, not a bug. GitHub exempts workflow_dispatch from that rule, so
13
+ # the last step here explicitly dispatches ci.yml against the new tag
14
+ # using that same GITHUB_TOKEN. No extra token/secret is needed.
15
+ #
16
+ # To run: Actions -> Release -> Run workflow, with the version to
17
+ # release (e.g. "0.1.13", no "v" prefix). Then watch the "CI" workflow
18
+ # run that starts against the new tag — that run is the actual publish.
19
+ name: Release
20
+
21
+ on:
22
+ workflow_dispatch:
23
+ inputs:
24
+ version:
25
+ description: "Version to release (e.g. 0.1.2)"
26
+ required: true
27
+ type: string
28
+
29
+ permissions:
30
+ contents: write
31
+ actions: write
32
+
33
+ jobs:
34
+ release:
35
+ name: Tag and push release
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
39
+ with:
40
+ fetch-depth: 0
41
+
42
+ - name: Check version is not already published
43
+ run: |
44
+ version="${{ inputs.version }}"
45
+ status=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/python-cad-tools/${version}/json")
46
+ if [ "$status" = "200" ]; then
47
+ echo "::error::python-cad-tools ${version} is already published on PyPI. This looks like a duplicate release attempt (a previous run likely already tagged and uploaded it) — choose a new version instead of re-running with the same one."
48
+ exit 1
49
+ fi
50
+
51
+ - name: Create and push tag
52
+ run: |
53
+ git config user.name "github-actions"
54
+ git config user.email "github-actions@github.com"
55
+ git tag "v${{ inputs.version }}"
56
+ git push origin "v${{ inputs.version }}"
57
+
58
+ - name: Trigger CI publish run for the new tag
59
+ env:
60
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61
+ run: gh workflow run ci.yml --repo "${{ github.repository }}" --ref "v${{ inputs.version }}"
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env python3
2
+ """Run the LangChain AutoCommit CLI for a verified SpecRepo change."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ import shutil
8
+ import site
9
+ import subprocess
10
+ import sys
11
+ from pathlib import Path
12
+ from typing import NoReturn
13
+
14
+ AUTOCOMMIT_REPOSITORY = "git+https://github.com/brandon-benge/langchain_autocommit.git"
15
+ CONFIGURATION_GUIDE = "https://github.com/brandon-benge/langchain_autocommit/blob/main/README.md#config-overrides"
16
+ EX_USAGE = 64
17
+
18
+
19
+ def print_usage() -> None:
20
+ print(
21
+ 'Usage: specrepo-autocommit "<summary of what changed>" [--no-push] '
22
+ "[--config-file <path>] [--env-var-name <NAME>] [--base-url <URL>] "
23
+ "[--model <MODEL>]\n\n"
24
+ "Runs autocommit on the current git branch.\n"
25
+ "--config-file points to the YAML configuration to use; defaults to "
26
+ "AUTOCOMMIT_PARAMS, then to .autoconfig.yaml in this repository.\n"
27
+ "--no-push commits locally without pushing to the remote.\n"
28
+ "--env-var-name, --base-url, and --model override the LLM API key "
29
+ "environment variable, base URL, and model that .autoconfig.yaml "
30
+ "otherwise supplies, e.g. to point at the AI Settings selected in "
31
+ "the Mac app.",
32
+ file=sys.stderr,
33
+ )
34
+
35
+
36
+ def fail(message: str, *, config_path: Path | None = None, code: int = 1) -> NoReturn:
37
+ print(message, file=sys.stderr)
38
+ if config_path is not None:
39
+ print(f"AUTOCOMMIT_PARAMS location: {config_path}", file=sys.stderr)
40
+ print(
41
+ f"Update that file as needed. Configuration guide: {CONFIGURATION_GUIDE}",
42
+ file=sys.stderr,
43
+ )
44
+ raise SystemExit(code)
45
+
46
+
47
+ def get_config_path(explicit_path: str | None = None) -> Path:
48
+ if explicit_path:
49
+ config_path = Path(os.path.expandvars(explicit_path)).expanduser().resolve()
50
+ print(f"--config-file is set to: {config_path}", flush=True)
51
+ else:
52
+ raw_path = os.environ.get("AUTOCOMMIT_PARAMS", "").strip()
53
+ if raw_path:
54
+ config_path = Path(os.path.expandvars(raw_path)).expanduser().resolve()
55
+ print(f"AUTOCOMMIT_PARAMS is set to: {config_path}", flush=True)
56
+ else:
57
+ config_path = (
58
+ Path(__file__).resolve().parent.parent.parent / ".autoconfig.yaml"
59
+ )
60
+ print(f"AUTOCOMMIT_PARAMS not set, using local fallback: {config_path}", flush=True)
61
+
62
+ if not config_path.is_file():
63
+ fail(
64
+ "Autocommit blocked: the configuration file does not exist or is not a regular file.",
65
+ config_path=config_path,
66
+ )
67
+
68
+ return config_path
69
+
70
+
71
+ def get_current_branch(config_path: Path) -> str:
72
+ try:
73
+ symbolic_ref = subprocess.run(
74
+ ["git", "symbolic-ref", "--quiet", "--short", "HEAD"],
75
+ check=False,
76
+ capture_output=True,
77
+ text=True,
78
+ )
79
+ branch = symbolic_ref.stdout.strip()
80
+
81
+ if not branch:
82
+ revision = subprocess.run(
83
+ ["git", "rev-parse", "--short", "HEAD"],
84
+ check=False,
85
+ capture_output=True,
86
+ text=True,
87
+ )
88
+ branch = revision.stdout.strip()
89
+ except OSError as error:
90
+ fail(
91
+ f"Autocommit blocked: could not run git: {error}",
92
+ config_path=config_path,
93
+ )
94
+
95
+ if not branch:
96
+ fail(
97
+ "Autocommit blocked: could not determine the current git branch.",
98
+ config_path=config_path,
99
+ )
100
+
101
+ return branch
102
+
103
+
104
+ def find_autocommit() -> str | None:
105
+ executable = shutil.which("autocommit")
106
+ if executable:
107
+ return executable
108
+
109
+ scripts_directory = Path(site.getuserbase()) / ("Scripts" if os.name == "nt" else "bin")
110
+ candidate = scripts_directory / ("autocommit.exe" if os.name == "nt" else "autocommit")
111
+ return str(candidate) if candidate.is_file() else None
112
+
113
+
114
+ def ensure_autocommit_installed(config_path: Path) -> str:
115
+ executable = find_autocommit()
116
+ if executable:
117
+ return executable
118
+
119
+ print("autocommit CLI not found. Installing it with the current Python...")
120
+ try:
121
+ installation = subprocess.run(
122
+ [
123
+ sys.executable,
124
+ "-m",
125
+ "pip",
126
+ "install",
127
+ "--user",
128
+ AUTOCOMMIT_REPOSITORY,
129
+ ],
130
+ check=False,
131
+ )
132
+ except OSError as error:
133
+ fail(
134
+ f"Autocommit installation failed: {error}",
135
+ config_path=config_path,
136
+ )
137
+
138
+ if installation.returncode != 0:
139
+ fail(
140
+ f"Autocommit installation failed with exit code {installation.returncode}.",
141
+ config_path=config_path,
142
+ code=installation.returncode,
143
+ )
144
+
145
+ executable = find_autocommit()
146
+ if not executable:
147
+ fail(
148
+ "Autocommit was installed but its executable could not be found.",
149
+ config_path=config_path,
150
+ )
151
+
152
+ print("autocommit installed successfully.")
153
+ return executable
154
+
155
+
156
+ def run_autocommit(
157
+ executable: str,
158
+ config_path: Path,
159
+ summary: str,
160
+ branch: str,
161
+ no_push: bool = False,
162
+ env_var_name: str | None = None,
163
+ base_url: str | None = None,
164
+ model: str | None = None,
165
+ ) -> None:
166
+ print(f"Running autocommit on branch {branch}.")
167
+ command = [
168
+ executable,
169
+ "--yes",
170
+ "--config-file",
171
+ str(config_path),
172
+ "-c",
173
+ summary,
174
+ ]
175
+ if no_push:
176
+ command.append("--no-push")
177
+ if env_var_name:
178
+ command += ["--env-var", "--env-var-name", env_var_name]
179
+ if base_url:
180
+ command += ["--base-url", base_url]
181
+ if model:
182
+ command += ["--model", model]
183
+ try:
184
+ result = subprocess.run(command, check=False)
185
+ except OSError as error:
186
+ fail(
187
+ f"Autocommit failed to start: {error}",
188
+ config_path=config_path,
189
+ )
190
+
191
+ if result.returncode != 0:
192
+ fail(
193
+ f"Autocommit failed with exit code {result.returncode}.",
194
+ config_path=config_path,
195
+ code=result.returncode if result.returncode > 0 else 1,
196
+ )
197
+
198
+
199
+ def main(argv: list[str]) -> int:
200
+ # Extract --no-push, --config-file <path>, and the LLM override flags
201
+ # before joining the remainder into the summary.
202
+ no_push = False
203
+ config_file: str | None = None
204
+ env_var_name: str | None = None
205
+ base_url: str | None = None
206
+ model: str | None = None
207
+ positional: list[str] = []
208
+ args_iter = iter(argv[1:])
209
+ for arg in args_iter:
210
+ if arg == "--no-push":
211
+ no_push = True
212
+ elif arg in ("--config-file", "--env-var-name", "--base-url", "--model"):
213
+ try:
214
+ value = next(args_iter)
215
+ except StopIteration:
216
+ print_usage()
217
+ fail(
218
+ f"Autocommit blocked: {arg} requires a value argument.",
219
+ code=EX_USAGE,
220
+ )
221
+ if arg == "--config-file":
222
+ config_file = value
223
+ elif arg == "--env-var-name":
224
+ env_var_name = value
225
+ elif arg == "--base-url":
226
+ base_url = value
227
+ else:
228
+ model = value
229
+ else:
230
+ positional.append(arg)
231
+
232
+ config_path = get_config_path(config_file)
233
+
234
+ if not positional or not " ".join(positional).strip():
235
+ print_usage()
236
+ fail(
237
+ "Autocommit blocked: a summary of what changed is required.",
238
+ config_path=config_path,
239
+ code=EX_USAGE,
240
+ )
241
+
242
+ summary = " ".join(positional).strip()
243
+ branch = get_current_branch(config_path)
244
+ executable = ensure_autocommit_installed(config_path)
245
+ run_autocommit(
246
+ executable,
247
+ config_path,
248
+ summary,
249
+ branch,
250
+ no_push=no_push,
251
+ env_var_name=env_var_name,
252
+ base_url=base_url,
253
+ model=model,
254
+ )
255
+ return 0
256
+
257
+
258
+ if __name__ == "__main__":
259
+ raise SystemExit(main(sys.argv))
@@ -7,6 +7,66 @@ stable release is published.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.16] - 2026-09-22
11
+
12
+ ### Fixed
13
+
14
+ - `python-cad --version` (and every other CLI invocation) no longer requires
15
+ `build123d`/the rest of the CAD toolchain to be importable: `cli.py`'s
16
+ `ValidationIssue` import — annotation-only, never evaluated at runtime
17
+ under this module's `from __future__ import annotations` — moved behind
18
+ `TYPE_CHECKING`. This was silently blocking every release since 0.1.14:
19
+ `build-publish` requires `tests/packaging` to pass, and its
20
+ clean-install-then-`--version` check installs the wheel with `--no-deps`,
21
+ which cannot satisfy the transitive `build123d` import `--version` didn't
22
+ actually need. 0.1.14 and 0.1.15 were tagged but never reached PyPI as a
23
+ result; 0.1.13 remained the latest published release throughout.
24
+
25
+ ## [0.1.15] - 2026-09-22
26
+
27
+ ### Changed
28
+
29
+ - `models/**/*.py` no longer needs an explicit `source-inputs` entry, at any
30
+ package depth and whether or not it has an `__init__.py`. `models/` is the
31
+ one directory a project is expected to keep adding files to over its
32
+ lifetime — one new module per new design object — so requiring a
33
+ `pyproject.toml` edit for each new file added no safety benefit: the build
34
+ manifest's `source_set_hash` already covers every file actually imported,
35
+ declared or not. `config.py`, `model.py`, `drawing_annotations.py`, and
36
+ `pyproject.toml` itself are unaffected and still require explicit
37
+ declaration, as does any other project-root Python file or data file read
38
+ through the public context. See `docs/project-configuration.md`.
39
+
40
+ ## [0.1.14] - 2026-08-13
41
+
42
+ ### Added
43
+
44
+ - New public `python_cad_tools.recipes` module: an opt-in, declarative
45
+ construction-recipe vocabulary (`RectangleProfile`, `CircleProfile`,
46
+ `ExtrudedProfile`, `DifferenceRecipe`, `evaluate`) that lets Tier 1
47
+ authoring produce parametric BREP IFC geometry
48
+ (`IfcExtrudedAreaSolid`/`SweptSolid`, `IfcBooleanResult`/`CSG`) instead of
49
+ only tessellated meshes. New `DesignElement.recipe` field, appended last;
50
+ `geometry` may now be `None` when a recipe is present. Recipes are
51
+ strictly opt-in per element — a model with no recipes produces IFC output
52
+ byte-identical to before this change, since neither recipe type adds a
53
+ unit-assignment entry. See `docs/neutral-model.md#construction-recipes`.
54
+ - The IFC validation sidecar gains additive `element_representation_types`
55
+ and `element_topology` keys; the design manifest gains additive
56
+ `recipe_kind` and `topology` per-element keys. `schema_version` is
57
+ unchanged on both.
58
+
59
+ ### Changed
60
+
61
+ - The IFC sidecar's `bounds_mm` is now the union of tessellation-derived
62
+ bounds and evaluated-solid bounds, so BREP-only and mixed models report
63
+ correct bounds (a BREP element emits no `IfcCartesianPointList3D`, which
64
+ the previous derivation depended on exclusively).
65
+ - `python-cad validate`'s CLI error message now includes each failing
66
+ issue's `element_id` (formatted as `code[element_id]: message`) when the
67
+ issue has one, instead of only `code: message`. Issues without an
68
+ element, such as `model-id`, are unaffected.
69
+
10
70
  ## [0.1.11] - 2026-08-11
11
71
 
12
72
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-cad-tools
3
- Version: 0.1.11
3
+ Version: 0.1.16
4
4
  Summary: Typed, headless Python tooling for CAD/BIM models and artifacts
5
5
  Author: Brandon Benge
6
6
  License: AGPL-3.0-only
@@ -187,6 +187,12 @@ Project code should preserve stable semantic IDs, keep geometry parametric, and
187
187
  create geometry and metadata together. Generated artifacts are outputs, never
188
188
  design inputs.
189
189
 
190
+ `python_cad_tools.recipes` lets an element opt into parametric BREP IFC
191
+ geometry (`IfcExtrudedAreaSolid`/`SweptSolid`, `IfcBooleanResult`/`CSG`)
192
+ instead of the default tessellated mesh, verified by a topology round-trip
193
+ after every build. See
194
+ [`docs/neutral-model.md#construction-recipes`](docs/neutral-model.md#construction-recipes).
195
+
190
196
  Project-owned drawing annotations use the typed, renderer-independent boundary
191
197
  documented in [`docs/drawing-extensions.md`](docs/drawing-extensions.md). One
192
198
  annotation set is validated and rendered consistently to SVG, DXF, and PDF
@@ -131,6 +131,12 @@ Project code should preserve stable semantic IDs, keep geometry parametric, and
131
131
  create geometry and metadata together. Generated artifacts are outputs, never
132
132
  design inputs.
133
133
 
134
+ `python_cad_tools.recipes` lets an element opt into parametric BREP IFC
135
+ geometry (`IfcExtrudedAreaSolid`/`SweptSolid`, `IfcBooleanResult`/`CSG`)
136
+ instead of the default tessellated mesh, verified by a topology round-trip
137
+ after every build. See
138
+ [`docs/neutral-model.md#construction-recipes`](docs/neutral-model.md#construction-recipes).
139
+
134
140
  Project-owned drawing annotations use the typed, renderer-independent boundary
135
141
  documented in [`docs/drawing-extensions.md`](docs/drawing-extensions.md). One
136
142
  annotation set is validated and rendered consistently to SVG, DXF, and PDF