solverforge 0.4.0__tar.gz → 0.5.0__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 (281) hide show
  1. solverforge-0.5.0/.github/workflows/ci.yml +69 -0
  2. {solverforge-0.4.0 → solverforge-0.5.0}/.github/workflows/release.yml +11 -16
  3. solverforge-0.5.0/AGENTS.md +121 -0
  4. solverforge-0.5.0/CHANGELOG.md +53 -0
  5. {solverforge-0.4.0 → solverforge-0.5.0}/Cargo.lock +78 -248
  6. solverforge-0.5.0/Cargo.toml +49 -0
  7. {solverforge-0.4.0 → solverforge-0.5.0}/Makefile +61 -16
  8. solverforge-0.5.0/PKG-INFO +336 -0
  9. solverforge-0.5.0/README.md +304 -0
  10. solverforge-0.5.0/WIREFRAME.md +306 -0
  11. solverforge-0.5.0/examples/solverforge_deliveries/README.md +85 -0
  12. solverforge-0.5.0/examples/solverforge_deliveries/__init__.py +23 -0
  13. solverforge-0.5.0/examples/solverforge_deliveries/__main__.py +32 -0
  14. solverforge-0.5.0/examples/solverforge_deliveries/solver.toml +51 -0
  15. solverforge-0.5.0/examples/solverforge_deliveries/src/__init__.py +1 -0
  16. solverforge-0.5.0/examples/solverforge_deliveries/src/api/__init__.py +1 -0
  17. solverforge-0.5.0/examples/solverforge_deliveries/src/api/dto.py +215 -0
  18. solverforge-0.5.0/examples/solverforge_deliveries/src/api/mod.py +3 -0
  19. solverforge-0.5.0/examples/solverforge_deliveries/src/api/routes.py +239 -0
  20. solverforge-0.5.0/examples/solverforge_deliveries/src/constraints/__init__.py +5 -0
  21. solverforge-0.5.0/examples/solverforge_deliveries/src/constraints/mod.py +47 -0
  22. solverforge-0.5.0/examples/solverforge_deliveries/src/data/__init__.py +5 -0
  23. solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/__init__.py +5 -0
  24. solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/entrypoints.py +213 -0
  25. solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/locations.json +1472 -0
  26. solverforge-0.5.0/examples/solverforge_deliveries/src/data/mod.py +1 -0
  27. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/__init__.py +33 -0
  28. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/delivery.py +32 -0
  29. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/metrics.py +404 -0
  30. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/mod.py +1 -0
  31. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/plan.py +84 -0
  32. solverforge-0.5.0/examples/solverforge_deliveries/src/domain/vehicle.py +41 -0
  33. solverforge-0.5.0/examples/solverforge_deliveries/src/lib.py +34 -0
  34. solverforge-0.5.0/examples/solverforge_deliveries/src/main.py +22 -0
  35. solverforge-0.5.0/examples/solverforge_deliveries/src/solver/__init__.py +5 -0
  36. solverforge-0.5.0/examples/solverforge_deliveries/src/solver/mod.py +1 -0
  37. solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/__init__.py +196 -0
  38. solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/mod.py +7 -0
  39. solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/payload.py +86 -0
  40. solverforge-0.5.0/examples/solverforge_deliveries/static/app/main.mjs +287 -0
  41. solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/core.mjs +57 -0
  42. solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/formatters.mjs +53 -0
  43. solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/preview.mjs +154 -0
  44. solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/timeline.mjs +94 -0
  45. solverforge-0.5.0/examples/solverforge_deliveries/static/app/models.mjs +8 -0
  46. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/api-guide.mjs +29 -0
  47. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/components.mjs +44 -0
  48. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/data-tables.mjs +98 -0
  49. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/layout.mjs +123 -0
  50. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/lifecycle.mjs +23 -0
  51. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/modals.mjs +63 -0
  52. solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/overview.mjs +172 -0
  53. solverforge-0.5.0/examples/solverforge_deliveries/static/app.css +196 -0
  54. solverforge-0.5.0/examples/solverforge_deliveries/static/app.js +3 -0
  55. solverforge-0.5.0/examples/solverforge_deliveries/static/generated/ui-model.json +25 -0
  56. solverforge-0.5.0/examples/solverforge_deliveries/static/index.html +22 -0
  57. solverforge-0.5.0/examples/solverforge_deliveries/static/sf-config.json +4 -0
  58. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/README.md +26 -8
  59. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/dto.py +29 -9
  60. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/routes.py +24 -4
  61. solverforge-0.5.0/examples/solverforge_hospital/src/api/sse.py +42 -0
  62. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/payload.py +18 -4
  63. {solverforge-0.4.0 → solverforge-0.5.0}/pyproject.toml +1 -1
  64. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/__init__.py +21 -4
  65. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/_native.pyi +12 -2
  66. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/constraints.py +220 -8
  67. solverforge-0.5.0/python/solverforge/decorators.py +146 -0
  68. solverforge-0.5.0/python/solverforge/fields.py +133 -0
  69. solverforge-0.5.0/python/solverforge/groups.py +99 -0
  70. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/model.py +38 -5
  71. solverforge-0.5.0/python/solverforge/ui.py +29 -0
  72. {solverforge-0.4.0 → solverforge-0.5.0}/scripts/verify_release_artifacts.py +48 -13
  73. {solverforge-0.4.0 → solverforge-0.5.0}/scripts/verify_solverforge_release_base.py +11 -26
  74. {solverforge-0.4.0 → solverforge-0.5.0}/src/bindings.rs +2 -0
  75. solverforge-0.5.0/src/constraints/evaluate.rs +159 -0
  76. solverforge-0.5.0/src/constraints/list_precedence.rs +767 -0
  77. {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/mod.rs +1 -0
  78. {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/state.rs +884 -159
  79. {solverforge-0.4.0 → solverforge-0.5.0}/src/lib.rs +1 -0
  80. {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/jobs.rs +13 -1
  81. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/dynamic_scalar_search.rs +2335 -197
  82. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/mod.rs +4 -2
  83. solverforge-0.5.0/src/schema/parse.rs +260 -0
  84. solverforge-0.5.0/src/schema/types.rs +112 -0
  85. solverforge-0.5.0/src/schema/validate.rs +38 -0
  86. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/api.rs +13 -4
  87. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/solvable.rs +7 -2
  88. solverforge-0.5.0/src/state/callback_view.rs +294 -0
  89. {solverforge-0.4.0 → solverforge-0.5.0}/src/state/entity_table.rs +3 -1
  90. solverforge-0.5.0/src/state/marshal.rs +349 -0
  91. {solverforge-0.4.0 → solverforge-0.5.0}/src/state/mod.rs +1 -0
  92. solverforge-0.5.0/src/state/solution.rs +465 -0
  93. solverforge-0.5.0/src/ui.rs +194 -0
  94. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_constraints.py +298 -1
  95. solverforge-0.5.0/tests/python/test_deliveries_example.py +329 -0
  96. solverforge-0.5.0/tests/python/test_deliveries_frontend_app.py +255 -0
  97. solverforge-0.5.0/tests/python/test_examples_import_surface.py +63 -0
  98. solverforge-0.5.0/tests/python/test_examples_playwright.py +296 -0
  99. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_hospital_frontend_app.py +110 -7
  100. solverforge-0.5.0/tests/python/test_list_solving.py +1472 -0
  101. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_manager.py +36 -1
  102. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_release_metadata.py +83 -10
  103. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_scalar_solving.py +682 -3
  104. solverforge-0.5.0/tests/python/test_ui_assets.py +125 -0
  105. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/constraint_set.rs +5 -0
  106. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/descriptor.rs +6 -0
  107. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/runtime_slots.rs +20 -4
  108. solverforge-0.5.0/tests/rust/state_clone.rs +226 -0
  109. solverforge-0.4.0/.github/workflows/ci.yml +0 -46
  110. solverforge-0.4.0/AGENTS.md +0 -62
  111. solverforge-0.4.0/Cargo.toml +0 -51
  112. solverforge-0.4.0/PKG-INFO +0 -187
  113. solverforge-0.4.0/README.md +0 -155
  114. solverforge-0.4.0/WIREFRAME.md +0 -152
  115. solverforge-0.4.0/docs/callback-contract.md +0 -18
  116. solverforge-0.4.0/docs/dynamic-move-parity-plan.md +0 -203
  117. solverforge-0.4.0/docs/goal.md +0 -305
  118. solverforge-0.4.0/docs/non-goals.md +0 -9
  119. solverforge-0.4.0/docs/release.md +0 -90
  120. solverforge-0.4.0/docs/threading.md +0 -12
  121. solverforge-0.4.0/docs/upstream-contract.md +0 -33
  122. solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/jetbrains-mono.woff2 +0 -0
  123. solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/space-grotesk.woff2 +0 -0
  124. solverforge-0.4.0/examples/solverforge_hospital/static/sf/img/ouroboros.svg +0 -60
  125. solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.css +0 -77
  126. solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.js +0 -165
  127. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.css +0 -2490
  128. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.js +0 -4012
  129. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.mjs +0 -3987
  130. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.css +0 -2490
  131. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.js +0 -4012
  132. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.mjs +0 -3987
  133. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/fontawesome.min.css +0 -9
  134. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/solid.min.css +0 -6
  135. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  136. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  137. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.css +0 -1
  138. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.js +0 -2
  139. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.css +0 -661
  140. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.js +0 -6
  141. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/split/split.min.js +0 -3
  142. solverforge-0.4.0/python/solverforge/decorators.py +0 -97
  143. solverforge-0.4.0/python/solverforge/fields.py +0 -61
  144. solverforge-0.4.0/src/constraints/evaluate.rs +0 -80
  145. solverforge-0.4.0/src/schema/parse.rs +0 -119
  146. solverforge-0.4.0/src/schema/types.rs +0 -44
  147. solverforge-0.4.0/src/schema/validate.rs +0 -20
  148. solverforge-0.4.0/src/state/marshal.rs +0 -155
  149. solverforge-0.4.0/src/state/solution.rs +0 -233
  150. solverforge-0.4.0/tests/python/test_list_solving.py +0 -336
  151. solverforge-0.4.0/tests/rust/state_clone.rs +0 -97
  152. {solverforge-0.4.0 → solverforge-0.5.0}/.gitignore +0 -0
  153. {solverforge-0.4.0 → solverforge-0.5.0}/.pre-commit-config.yaml +0 -0
  154. {solverforge-0.4.0 → solverforge-0.5.0}/.python-version +0 -0
  155. {solverforge-0.4.0 → solverforge-0.5.0}/LICENSE +0 -0
  156. {solverforge-0.4.0 → solverforge-0.5.0}/examples/list_tsp.py +0 -0
  157. {solverforge-0.4.0 → solverforge-0.5.0}/examples/mixed_job_shop.py +0 -0
  158. {solverforge-0.4.0 → solverforge-0.5.0}/examples/nqueens.py +0 -0
  159. {solverforge-0.4.0 → solverforge-0.5.0}/examples/shift_scheduling.py +0 -0
  160. {solverforge-0.4.0/examples/solverforge_hospital → solverforge-0.5.0/examples/solverforge_deliveries}/src/api/sse.py +0 -0
  161. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/__init__.py +0 -0
  162. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/__main__.py +0 -0
  163. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/solver.toml +0 -0
  164. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/__init__.py +0 -0
  165. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/__init__.py +0 -0
  166. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/mod.py +0 -0
  167. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/__init__.py +0 -0
  168. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/assigned_shift.py +0 -0
  169. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/balance_assignments.py +0 -0
  170. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/desired_day.py +0 -0
  171. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/minimum_rest.py +0 -0
  172. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/mod.py +0 -0
  173. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/one_shift_per_day.py +0 -0
  174. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/overlapping_shift.py +0 -0
  175. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/required_skill.py +0 -0
  176. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/unavailable_employee.py +0 -0
  177. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/undesired_day.py +0 -0
  178. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/__init__.py +0 -0
  179. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/LARGE.json +0 -0
  180. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/__init__.py +0 -0
  181. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/availability.py +0 -0
  182. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/cohorts.py +0 -0
  183. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/coverage.py +0 -0
  184. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/demand.py +0 -0
  185. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/employees.py +0 -0
  186. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/entrypoints.py +0 -0
  187. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/large.py +0 -0
  188. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/preferences.py +0 -0
  189. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/shifts.py +0 -0
  190. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/skills.py +0 -0
  191. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/time_utils.py +0 -0
  192. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/validation.py +0 -0
  193. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/vocabulary.py +0 -0
  194. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/witness.py +0 -0
  195. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/mod.py +0 -0
  196. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/__init__.py +0 -0
  197. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/care_hub.py +0 -0
  198. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/employee.py +0 -0
  199. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/mod.py +0 -0
  200. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/plan.py +0 -0
  201. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/lib.py +0 -0
  202. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/main.py +0 -0
  203. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/__init__.py +0 -0
  204. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/mod.py +0 -0
  205. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/__init__.py +0 -0
  206. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/mod.py +0 -0
  207. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/main.mjs +0 -0
  208. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/analysis-modal.mjs +0 -0
  209. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/datetime.mjs +0 -0
  210. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/employee-view.mjs +0 -0
  211. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/grouping.mjs +0 -0
  212. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/identity.mjs +0 -0
  213. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/location-view.mjs +0 -0
  214. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/presentation.mjs +0 -0
  215. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/rail-renderer.mjs +0 -0
  216. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/api-guide.mjs +0 -0
  217. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/app-shell.mjs +0 -0
  218. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/app-state.mjs +0 -0
  219. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/config-loader.mjs +0 -0
  220. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/data-panel.mjs +0 -0
  221. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/solver-controller.mjs +0 -0
  222. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/views/registry.mjs +0 -0
  223. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/generated/ui-model.json +0 -0
  224. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/index.html +0 -0
  225. {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/sf-config.json +0 -0
  226. {solverforge-0.4.0 → solverforge-0.5.0}/examples/vrp_owner_hooks.py +0 -0
  227. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/config.py +0 -0
  228. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/console.py +0 -0
  229. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/errors.py +0 -0
  230. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/events.py +0 -0
  231. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/joiner.py +0 -0
  232. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/manager.py +0 -0
  233. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/py.typed +0 -0
  234. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/score.py +0 -0
  235. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/solver.py +0 -0
  236. {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/typing.py +0 -0
  237. {solverforge-0.4.0 → solverforge-0.5.0}/rust-toolchain.toml +0 -0
  238. {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/call.rs +0 -0
  239. {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/mod.rs +0 -0
  240. {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/registry.rs +0 -0
  241. {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/threading.rs +0 -0
  242. {solverforge-0.4.0 → solverforge-0.5.0}/src/config.rs +0 -0
  243. {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/incremental.rs +0 -0
  244. {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/matches.rs +0 -0
  245. {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/stream_plan.rs +0 -0
  246. {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/extractor.rs +0 -0
  247. {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/mod.rs +0 -0
  248. {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/variable.rs +0 -0
  249. {solverforge-0.4.0 → solverforge-0.5.0}/src/error.rs +0 -0
  250. {solverforge-0.4.0 → solverforge-0.5.0}/src/intern.rs +0 -0
  251. {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/events.rs +0 -0
  252. {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/mod.rs +0 -0
  253. {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/entity.rs +0 -0
  254. {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/list.rs +0 -0
  255. {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/mod.rs +0 -0
  256. {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/solution.rs +0 -0
  257. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/distance.rs +0 -0
  258. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/list_slots.rs +0 -0
  259. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/scalar_slots.rs +0 -0
  260. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/static_fns.rs +0 -0
  261. {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/thread_local.rs +0 -0
  262. {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/build.rs +0 -0
  263. {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/mod.rs +0 -0
  264. {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/python.rs +0 -0
  265. {solverforge-0.4.0 → solverforge-0.5.0}/src/score.rs +0 -0
  266. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/console.rs +0 -0
  267. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/mod.rs +0 -0
  268. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/progress.rs +0 -0
  269. {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/result.rs +0 -0
  270. {solverforge-0.4.0 → solverforge-0.5.0}/src/state/clone.rs +0 -0
  271. {solverforge-0.4.0 → solverforge-0.5.0}/src/state/variables.rs +0 -0
  272. {solverforge-0.4.0 → solverforge-0.5.0}/src/value.rs +0 -0
  273. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_config.py +0 -0
  274. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_decorators.py +0 -0
  275. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_hospital_example.py +0 -0
  276. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_mixed_solving.py +0 -0
  277. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_threading.py +0 -0
  278. {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_tracebacks.py +0 -0
  279. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/manager.rs +0 -0
  280. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/score.rs +0 -0
  281. {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust.rs +0 -0
@@ -0,0 +1,69 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ env:
12
+ PYTHON_VERSION: "3.14"
13
+ RUST_VERSION: "1.95.0"
14
+
15
+ jobs:
16
+ ci-local:
17
+ name: local CI gate
18
+ runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'rust' }}
19
+ steps:
20
+ - name: Checkout solverforge-py
21
+ uses: actions/checkout@v6
22
+
23
+ - name: Set up Python
24
+ shell: bash
25
+ run: |
26
+ curl --retry 5 --retry-all-errors --retry-delay 5 \
27
+ -LsSf https://astral.sh/uv/install.sh | sh
28
+ echo "${HOME}/.local/bin" >> "${GITHUB_PATH}"
29
+ "${HOME}/.local/bin/uv" python install "${PYTHON_VERSION}"
30
+ host_python="$("${HOME}/.local/bin/uv" python find "${PYTHON_VERSION}")"
31
+ host_python_dir="$(dirname "${host_python}")"
32
+ host_python_libdir="$("${host_python}" -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR") or "")')"
33
+ echo "${host_python_dir}" >> "${GITHUB_PATH}"
34
+ echo "HOST_PYTHON=${host_python}" >> "${GITHUB_ENV}"
35
+ echo "PYO3_PYTHON=${host_python}" >> "${GITHUB_ENV}"
36
+ echo "PYTHON_SYS_EXECUTABLE=${host_python}" >> "${GITHUB_ENV}"
37
+ echo "LIBRARY_PATH=${host_python_libdir}:${LIBRARY_PATH:-}" >> "${GITHUB_ENV}"
38
+ echo "LD_LIBRARY_PATH=${host_python_libdir}:${LD_LIBRARY_PATH:-}" >> "${GITHUB_ENV}"
39
+ "${host_python}" --version
40
+
41
+ - name: Set up Rust
42
+ shell: bash
43
+ run: |
44
+ curl --retry 5 --retry-all-errors --retry-delay 5 \
45
+ --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
46
+ | sh -s -- -y --profile minimal --default-toolchain "${RUST_VERSION}" \
47
+ --component rustfmt --component clippy
48
+ if [ -f "${HOME}/.cargo/env" ]; then
49
+ . "${HOME}/.cargo/env"
50
+ echo "${HOME}/.cargo/bin" >> "${GITHUB_PATH}"
51
+ else
52
+ . /usr/local/cargo/env
53
+ echo "/usr/local/cargo/bin" >> "${GITHUB_PATH}"
54
+ fi
55
+ rustc --version
56
+ cargo --version
57
+
58
+ - name: Validate SolverForge release base
59
+ run: make release-base-check
60
+
61
+ - name: Install Playwright system dependencies
62
+ if: ${{ runner.os == 'Linux' }}
63
+ run: make install-playwright-system-deps
64
+
65
+ - name: Run local CI
66
+ run: make ci-local
67
+
68
+ - name: Build and verify local distributions
69
+ run: make build-dist dist-check smoke-wheel
@@ -1,16 +1,7 @@
1
1
  name: Release
2
2
 
3
3
  on:
4
- workflow_dispatch:
5
- inputs:
6
- repository:
7
- description: Publish target
8
- required: true
9
- default: testpypi
10
- type: choice
11
- options:
12
- - testpypi
13
- - pypi
4
+ workflow_dispatch: {}
14
5
  push:
15
6
  tags:
16
7
  - "v*.*.*"
@@ -25,6 +16,7 @@ env:
25
16
  jobs:
26
17
  sdist:
27
18
  name: source distribution
19
+ if: github.server_url == 'https://github.com'
28
20
  runs-on: ubuntu-latest
29
21
  steps:
30
22
  - name: Checkout solverforge-py
@@ -55,6 +47,7 @@ jobs:
55
47
 
56
48
  wheels:
57
49
  name: wheel ${{ matrix.os }} ${{ matrix.target }}
50
+ if: github.server_url == 'https://github.com'
58
51
  runs-on: ${{ matrix.os }}
59
52
  strategy:
60
53
  fail-fast: false
@@ -101,6 +94,7 @@ jobs:
101
94
 
102
95
  verify:
103
96
  name: verify artifacts
97
+ if: github.server_url == 'https://github.com'
104
98
  runs-on: ubuntu-latest
105
99
  needs: [sdist, wheels]
106
100
  steps:
@@ -140,10 +134,13 @@ jobs:
140
134
  name: publish to TestPyPI
141
135
  runs-on: ubuntu-latest
142
136
  needs: verify
143
- if: github.event_name == 'workflow_dispatch' && github.event.inputs.repository == 'testpypi'
137
+ if: >-
138
+ github.server_url == 'https://github.com' &&
139
+ github.event_name == 'workflow_dispatch'
144
140
  environment: testpypi
145
141
  permissions:
146
142
  contents: read
143
+ id-token: write
147
144
  steps:
148
145
  - name: Download verified distributions
149
146
  uses: actions/download-artifact@v8
@@ -155,15 +152,15 @@ jobs:
155
152
  uses: pypa/gh-action-pypi-publish@release/v1
156
153
  with:
157
154
  repository-url: https://test.pypi.org/legacy/
158
- password: ${{ secrets.TEST_PYPI_API_TOKEN }}
159
155
 
160
156
  publish-pypi:
161
157
  name: publish to PyPI
162
158
  runs-on: ubuntu-latest
163
159
  needs: verify
164
160
  if: >-
165
- (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
166
- (github.event_name == 'workflow_dispatch' && github.event.inputs.repository == 'pypi')
161
+ github.server_url == 'https://github.com' &&
162
+ github.event_name == 'push' &&
163
+ startsWith(github.ref, 'refs/tags/v')
167
164
  environment: pypi
168
165
  permissions:
169
166
  contents: read
@@ -187,8 +184,6 @@ jobs:
187
184
 
188
185
  expected = f"v{version}"
189
186
  actual = os.environ["GITHUB_REF_NAME"]
190
- if os.environ["GITHUB_EVENT_NAME"] == "workflow_dispatch":
191
- raise SystemExit(0)
192
187
  if actual != expected:
193
188
  raise SystemExit(f"tag {actual} does not match package version {expected}")
194
189
  PY
@@ -0,0 +1,121 @@
1
+ # Repository Guidelines
2
+
3
+ ## Project Structure & Module Organization
4
+
5
+ `solverforge-py` is a mixed Python/Rust binding package built with PyO3 and
6
+ maturin. Python package code lives under `python/solverforge/`; the native
7
+ extension, dynamic runtime bridge, callbacks, manager, and schema code live under
8
+ `src/`. Python tests are in `tests/python/`, Rust tests are in `tests/rust/`, and
9
+ examples are in `examples/`. The hospital and deliveries demos own their
10
+ FastAPI apps, app-specific static UI, generated UI models, and seed data under
11
+ `examples/solverforge_hospital/` and `examples/solverforge_deliveries/`;
12
+ shared `/sf/*` assets are served from the pinned `solverforge-ui` crate through
13
+ the native binding.
14
+ `WIREFRAME.md` is the as-built API/UI map; `README.md` carries installation,
15
+ callback/threading, boundary, and release contracts. There is no separate
16
+ `docs/` directory.
17
+
18
+ ## Build, Test, and Development Commands
19
+
20
+ - `make develop`: create `.venv`, install tools, and install the release native extension.
21
+ - `make install-playwright-system-deps`: install Chromium plus Linux shared
22
+ libraries required by Playwright browser tests in lean CI images.
23
+ - `make test`: run Rust tests with the local Python link setup, then pytest.
24
+ - `make test-quick`: run fast Python regressions without the example app tests.
25
+ - `make test-hospital`: run the hospital model, FastAPI/frontend lifecycle, and
26
+ hospital Playwright browser test.
27
+ - `make test-deliveries`: run the deliveries model, FastAPI/frontend lifecycle,
28
+ and deliveries Playwright browser test.
29
+ - `make test-examples-browser`: run the Playwright browser tests for both example apps.
30
+ - `make lint`: run rustfmt check, ruff, strict mypy, and clippy with warnings denied.
31
+ - `make docs-check`: verify the tracked README, AGENTS, WIREFRAME, and example
32
+ README surface exists and avoids known stale claims.
33
+ - `make release-base-check`: verify the exact crates.io SolverForge dependency
34
+ base in `Cargo.toml` and `Cargo.lock`.
35
+ - `make ci-local` or `make audit`: run the local CI simulation.
36
+ - `make pre-release`: run `release-base-check`, `ci-local`, release
37
+ distribution build/checks, and clean-wheel smoke test.
38
+ - `make hospital-run`: serve the hospital app on `APP_HOST=127.0.0.1 PORT=7860`.
39
+ - `make deliveries-run`: serve the deliveries app on `APP_HOST=127.0.0.1 PORT=7860`
40
+ unless `PORT` is overridden.
41
+
42
+ Use Rust `1.95.0` from `rust-toolchain.toml`. Python code targets Python `3.14`.
43
+
44
+ ## Coding Style & Naming Conventions
45
+
46
+ Python uses Ruff linting, strict mypy, and the 100-character line limit from
47
+ `pyproject.toml`; `make py-format` is available for an intentional Black pass.
48
+ Prefer typed public APIs and keep exports in `python/solverforge/__init__.py`
49
+ intentional. Use snake_case for Python modules, functions, and variables; use
50
+ PascalCase for classes. Rust follows rustfmt and clippy with `-D warnings`; keep
51
+ module names snake_case and public types descriptive.
52
+
53
+ ## Testing Guidelines
54
+
55
+ Add Python regression tests as `tests/python/test_*.py`. Add Rust integration or
56
+ unit coverage under `tests/rust/` or the relevant `src/` module. For binding
57
+ changes, prefer tests that prove Python behavior through the public `solverforge`
58
+ API, then add Rust tests only where native runtime behavior is directly changed.
59
+ Run the narrow suite first, then `make ci-local` for cross-language or
60
+ integration changes. Use `make test-hospital` or `make test-deliveries` when
61
+ touching either example app. Binding changes should normally prove behavior
62
+ through the public Python API and add Rust coverage only when native runtime
63
+ behavior changes directly.
64
+
65
+ ## Runtime & Callback Contracts
66
+
67
+ Python owns model authoring: classes, decorators, functions, lambdas, and
68
+ callbacks. `solverforge-py` owns the Python API, PyO3 binding code, Rust-owned
69
+ dynamic model state, callback invocation, marshaling, packaging, and example
70
+ apps. Upstream SolverForge owns the solver engine, phases, selectors, move
71
+ machinery, termination, telemetry, retained lifecycle, descriptors, and public
72
+ bridge seams. This checkout consumes public upstream crates through exact
73
+ registry pins in `Cargo.toml` and `Cargo.lock`; do not add private upstream
74
+ module dependencies or local path overrides for release work.
75
+
76
+ Python callbacks are the only constraint authoring surface. Callback exceptions
77
+ must preserve actionable Python tracebacks. Callback solution views must expose
78
+ ordinary solution-level lookup context while projecting entity/fact collections
79
+ from Rust-owned state. Callback code may be called many times and from multiple
80
+ worker threads on CPython 3.14 free-threaded, so treat solution-level lookup
81
+ context as immutable during a solve.
82
+
83
+ Do not fake unsupported behavior. Top-level `ConstraintFactory.join`,
84
+ `group_by`, `if_exists`, `if_not_exists`, and `flattened` remain explicit
85
+ unsupported methods until public bridge support exists for those top-level
86
+ semantics. Rust-only custom search and partitioner registration cannot be
87
+ claimed as Python-bindable without a public upstream seam.
88
+
89
+ ## Release Responsibilities
90
+
91
+ `pyproject.toml` owns PyPI metadata, version, Python requirement, optional
92
+ example dependencies, project URLs, classifiers, and maturin module settings.
93
+ `Cargo.toml` owns native crate metadata and the SolverForge Rust dependency
94
+ base; the package version must match `pyproject.toml`. `Cargo.lock` locks
95
+ reproducible Rust builds. The `Makefile` owns local release targets,
96
+ dependency-base checks, distribution builds, artifact validation, browser system
97
+ dependency setup, and `pre-release`. `.github/workflows/ci.yml` validates source
98
+ checkouts on GitHub and Forgejo, installs Playwright system dependencies on
99
+ Linux, and retries network toolchain bootstraps for transient runner DNS misses.
100
+ `.github/workflows/release.yml` builds sdists/wheels, verifies release
101
+ artifacts, publishes to TestPyPI only from manual workflow dispatch, and
102
+ publishes to PyPI only from a matching `v*.*.*` tag after the reviewed `pypi`
103
+ environment approves the job. `scripts/verify_release_artifacts.py` checks
104
+ deterministic artifact metadata/content, and
105
+ `tests/python/test_release_metadata.py` guards release metadata drift.
106
+
107
+ ## Commit & Pull Request Guidelines
108
+
109
+ The history uses concise Conventional Commit-style subjects such as
110
+ `fix(runtime): preserve scalar snapshots` or `test(manager): cover retained jobs`.
111
+ Pull requests should include the motivation, user-visible behavior, tests run,
112
+ and any linked issue. Include screenshots or short recordings for changes under
113
+ `examples/solverforge_hospital/static/` or
114
+ `examples/solverforge_deliveries/static/`.
115
+
116
+ ## Agent-Specific Instructions
117
+
118
+ Keep changes scoped to the requested surface. Do not rewrite runtime, callback,
119
+ manager, or API payload paths for a simple documentation, UI, naming, or wiring
120
+ task unless live evidence proves that path is the failing layer. Verify assumptions
121
+ from the repo before changing critical integration code.
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
+
5
+ ## [0.5.0](https://github.com/SolverForge/solverforge-py/compare/v0.4.1...v0.5.0) (2026-07-03)
6
+
7
+
8
+ ### Features
9
+
10
+ * **examples:** add deliveries Python app 0179084
11
+ * **model:** carry dynamic route and shadow hooks 83a8d41
12
+ * **runtime:** bind Python list route hooks fd51788
13
+ * **runtime:** broaden dynamic Python planning surface f04eefa
14
+ * **ui:** embed shared frontend assets ab30697
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **ci:** bootstrap Forgejo toolchains in workflow 8e5f791
20
+ * **ci:** install Playwright system dependencies b249fd1
21
+ * **ci:** retry toolchain bootstrap downloads cd60f76
22
+ * **ci:** run workflow from checkout root 8733fc3
23
+ * **ci:** select Forgejo runner labels 56ff4fc
24
+ * **deliveries:** recommend assigned-route insertions d59daea
25
+ * **examples:** report snapshot score in payloads 0bfcaa0
26
+ * **examples:** report solution scores in events bdcddd8
27
+ * **model:** validate scalar group names cfa2070
28
+ * **runtime:** align dynamic construction with core semantics 7cacda0
29
+ * **runtime:** cap first-fit required construction candidates 3666c20
30
+ * **runtime:** resolve dynamic slots against descriptors a2544be
31
+ * **runtime:** reuse required assignment construction streams 0caf06d
32
+ * **runtime:** use direct cursor for first-fit assignments 769a081
33
+ * **scoring:** return true shadow update deltas 88dc500
34
+ * **state:** preserve callback root fields 0aacef5
35
+
36
+
37
+ ### Tests
38
+
39
+ * **examples:** stabilize hospital browser smoke f11efd6
40
+ * **examples:** stub map tiles in browser smoke d69ca3e
41
+
42
+
43
+ ### Documentation and release
44
+
45
+ * **docs:** remove standalone docs surface b1c6e1f
46
+ * **release:** cut 0.5.0 metadata 4728014
47
+
48
+ ## [0.4.1](https://github.com/SolverForge/solverforge-py/compare/v0.4.0...v0.4.1) (2026-06-02)
49
+
50
+
51
+ ### Bug Fixes
52
+
53
+ * **deps:** resolve SolverForge crates from crates.io 73bfe4a