solverforge 0.4.0__tar.gz → 0.6.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 (311) hide show
  1. solverforge-0.6.0/.github/workflows/ci.yml +69 -0
  2. {solverforge-0.4.0 → solverforge-0.6.0}/.github/workflows/release.yml +27 -20
  3. solverforge-0.6.0/AGENTS.md +153 -0
  4. solverforge-0.6.0/CHANGELOG.md +61 -0
  5. {solverforge-0.4.0 → solverforge-0.6.0}/Cargo.lock +78 -248
  6. solverforge-0.6.0/Cargo.toml +49 -0
  7. {solverforge-0.4.0 → solverforge-0.6.0}/Makefile +72 -16
  8. solverforge-0.6.0/PKG-INFO +416 -0
  9. solverforge-0.6.0/README.md +384 -0
  10. solverforge-0.6.0/WIREFRAME.md +456 -0
  11. solverforge-0.6.0/examples/solverforge_deliveries/README.md +90 -0
  12. solverforge-0.6.0/examples/solverforge_deliveries/__init__.py +23 -0
  13. solverforge-0.6.0/examples/solverforge_deliveries/__main__.py +32 -0
  14. solverforge-0.6.0/examples/solverforge_deliveries/solver.toml +51 -0
  15. solverforge-0.6.0/examples/solverforge_deliveries/src/__init__.py +1 -0
  16. solverforge-0.6.0/examples/solverforge_deliveries/src/api/__init__.py +1 -0
  17. solverforge-0.6.0/examples/solverforge_deliveries/src/api/dto.py +233 -0
  18. solverforge-0.6.0/examples/solverforge_deliveries/src/api/mod.py +3 -0
  19. solverforge-0.6.0/examples/solverforge_deliveries/src/api/routes.py +239 -0
  20. solverforge-0.6.0/examples/solverforge_deliveries/src/constraints/__init__.py +5 -0
  21. solverforge-0.6.0/examples/solverforge_deliveries/src/constraints/mod.py +47 -0
  22. solverforge-0.6.0/examples/solverforge_deliveries/src/data/__init__.py +5 -0
  23. solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/__init__.py +5 -0
  24. solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/entrypoints.py +149 -0
  25. solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/locations.json +1472 -0
  26. solverforge-0.6.0/examples/solverforge_deliveries/src/data/mod.py +1 -0
  27. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/__init__.py +33 -0
  28. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/delivery.py +32 -0
  29. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/metrics.py +493 -0
  30. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/mod.py +1 -0
  31. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/plan.py +126 -0
  32. solverforge-0.6.0/examples/solverforge_deliveries/src/domain/vehicle.py +112 -0
  33. solverforge-0.6.0/examples/solverforge_deliveries/src/lib.py +34 -0
  34. solverforge-0.6.0/examples/solverforge_deliveries/src/main.py +22 -0
  35. solverforge-0.6.0/examples/solverforge_deliveries/src/solver/__init__.py +5 -0
  36. solverforge-0.6.0/examples/solverforge_deliveries/src/solver/mod.py +1 -0
  37. solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/__init__.py +196 -0
  38. solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/mod.py +7 -0
  39. solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/payload.py +86 -0
  40. solverforge-0.6.0/examples/solverforge_deliveries/static/app/main.mjs +287 -0
  41. solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/core.mjs +57 -0
  42. solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/formatters.mjs +53 -0
  43. solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/preview.mjs +154 -0
  44. solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/timeline.mjs +94 -0
  45. solverforge-0.6.0/examples/solverforge_deliveries/static/app/models.mjs +8 -0
  46. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/api-guide.mjs +29 -0
  47. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/components.mjs +44 -0
  48. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/data-tables.mjs +98 -0
  49. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/layout.mjs +123 -0
  50. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/lifecycle.mjs +23 -0
  51. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/modals.mjs +63 -0
  52. solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/overview.mjs +172 -0
  53. solverforge-0.6.0/examples/solverforge_deliveries/static/app.css +196 -0
  54. solverforge-0.6.0/examples/solverforge_deliveries/static/app.js +3 -0
  55. solverforge-0.6.0/examples/solverforge_deliveries/static/generated/ui-model.json +25 -0
  56. solverforge-0.6.0/examples/solverforge_deliveries/static/index.html +22 -0
  57. solverforge-0.6.0/examples/solverforge_deliveries/static/sf-config.json +4 -0
  58. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/README.md +35 -12
  59. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/solver.toml +2 -2
  60. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/dto.py +47 -9
  61. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/routes.py +24 -4
  62. solverforge-0.6.0/examples/solverforge_hospital/src/api/sse.py +42 -0
  63. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/plan.py +52 -7
  64. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/payload.py +18 -4
  65. {solverforge-0.4.0 → solverforge-0.6.0}/pyproject.toml +1 -1
  66. solverforge-0.6.0/python/solverforge/__init__.py +88 -0
  67. solverforge-0.6.0/python/solverforge/_native.pyi +72 -0
  68. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/config.py +27 -3
  69. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/constraints.py +252 -8
  70. solverforge-0.6.0/python/solverforge/decorators.py +234 -0
  71. solverforge-0.6.0/python/solverforge/fields.py +494 -0
  72. solverforge-0.6.0/python/solverforge/groups.py +167 -0
  73. solverforge-0.6.0/python/solverforge/joiner.py +39 -0
  74. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/manager.py +31 -5
  75. solverforge-0.6.0/python/solverforge/model.py +326 -0
  76. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/solver.py +6 -4
  77. solverforge-0.6.0/python/solverforge/ui.py +29 -0
  78. {solverforge-0.4.0 → solverforge-0.6.0}/scripts/verify_release_artifacts.py +48 -13
  79. {solverforge-0.4.0 → solverforge-0.6.0}/scripts/verify_solverforge_release_base.py +11 -26
  80. {solverforge-0.4.0 → solverforge-0.6.0}/src/bindings.rs +8 -0
  81. solverforge-0.6.0/src/config.rs +113 -0
  82. solverforge-0.6.0/src/constraints/compiled.rs +322 -0
  83. solverforge-0.6.0/src/constraints/evaluate.rs +159 -0
  84. solverforge-0.6.0/src/constraints/list_precedence.rs +935 -0
  85. {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/mod.rs +2 -0
  86. {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/state.rs +1280 -249
  87. solverforge-0.6.0/src/error.rs +44 -0
  88. {solverforge-0.4.0 → solverforge-0.6.0}/src/lib.rs +1 -0
  89. solverforge-0.6.0/src/manager/candidate_trace.rs +388 -0
  90. solverforge-0.6.0/src/manager/events.rs +564 -0
  91. {solverforge-0.4.0 → solverforge-0.6.0}/src/manager/jobs.rs +107 -20
  92. solverforge-0.6.0/src/manager/mod.rs +7 -0
  93. solverforge-0.6.0/src/manager/provenance.rs +205 -0
  94. solverforge-0.6.0/src/runtime/candidate_metric.rs +119 -0
  95. solverforge-0.6.0/src/runtime/dynamic_assignment_group.rs +471 -0
  96. solverforge-0.6.0/src/runtime/dynamic_provider.rs +291 -0
  97. solverforge-0.6.0/src/runtime/list_slots.rs +798 -0
  98. solverforge-0.6.0/src/runtime/mod.rs +46 -0
  99. solverforge-0.6.0/src/runtime/scalar_slots.rs +337 -0
  100. solverforge-0.6.0/src/schema/compiled.rs +43 -0
  101. {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/mod.rs +2 -0
  102. solverforge-0.6.0/src/schema/parse.rs +760 -0
  103. solverforge-0.6.0/src/schema/runtime_plan.rs +71 -0
  104. solverforge-0.6.0/src/schema/types.rs +266 -0
  105. solverforge-0.6.0/src/schema/validate.rs +118 -0
  106. {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/api.rs +32 -45
  107. {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/console.rs +14 -15
  108. solverforge-0.6.0/src/solver/solvable.rs +53 -0
  109. solverforge-0.6.0/src/state/callback_view.rs +616 -0
  110. solverforge-0.6.0/src/state/entity_table.rs +143 -0
  111. solverforge-0.6.0/src/state/marshal.rs +1195 -0
  112. {solverforge-0.4.0 → solverforge-0.6.0}/src/state/mod.rs +1 -0
  113. solverforge-0.6.0/src/state/solution.rs +844 -0
  114. solverforge-0.6.0/src/state/variables.rs +18 -0
  115. solverforge-0.6.0/src/ui.rs +194 -0
  116. solverforge-0.6.0/tests/python/test_candidate_trace_provenance.py +174 -0
  117. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_config.py +37 -8
  118. solverforge-0.6.0/tests/python/test_constraints.py +1440 -0
  119. solverforge-0.6.0/tests/python/test_decorators.py +606 -0
  120. solverforge-0.6.0/tests/python/test_deliveries_example.py +380 -0
  121. solverforge-0.6.0/tests/python/test_deliveries_frontend_app.py +289 -0
  122. solverforge-0.6.0/tests/python/test_examples_import_surface.py +63 -0
  123. solverforge-0.6.0/tests/python/test_examples_playwright.py +296 -0
  124. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_hospital_example.py +33 -3
  125. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_hospital_frontend_app.py +147 -9
  126. solverforge-0.6.0/tests/python/test_list_solving.py +2089 -0
  127. solverforge-0.6.0/tests/python/test_manager.py +372 -0
  128. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_release_metadata.py +81 -10
  129. solverforge-0.6.0/tests/python/test_scalar_solving.py +3275 -0
  130. solverforge-0.6.0/tests/python/test_tracebacks.py +185 -0
  131. solverforge-0.6.0/tests/python/test_ui_assets.py +125 -0
  132. solverforge-0.6.0/tests/rust/constraint_set.rs +45 -0
  133. {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/descriptor.rs +18 -6
  134. solverforge-0.6.0/tests/rust/runtime_slots.rs +226 -0
  135. solverforge-0.6.0/tests/rust/state_clone.rs +306 -0
  136. solverforge-0.4.0/.github/workflows/ci.yml +0 -46
  137. solverforge-0.4.0/AGENTS.md +0 -62
  138. solverforge-0.4.0/Cargo.toml +0 -51
  139. solverforge-0.4.0/PKG-INFO +0 -187
  140. solverforge-0.4.0/README.md +0 -155
  141. solverforge-0.4.0/WIREFRAME.md +0 -152
  142. solverforge-0.4.0/docs/callback-contract.md +0 -18
  143. solverforge-0.4.0/docs/dynamic-move-parity-plan.md +0 -203
  144. solverforge-0.4.0/docs/goal.md +0 -305
  145. solverforge-0.4.0/docs/non-goals.md +0 -9
  146. solverforge-0.4.0/docs/release.md +0 -90
  147. solverforge-0.4.0/docs/threading.md +0 -12
  148. solverforge-0.4.0/docs/upstream-contract.md +0 -33
  149. solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/jetbrains-mono.woff2 +0 -0
  150. solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/space-grotesk.woff2 +0 -0
  151. solverforge-0.4.0/examples/solverforge_hospital/static/sf/img/ouroboros.svg +0 -60
  152. solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.css +0 -77
  153. solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.js +0 -165
  154. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.css +0 -2490
  155. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.js +0 -4012
  156. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.mjs +0 -3987
  157. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.css +0 -2490
  158. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.js +0 -4012
  159. solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.mjs +0 -3987
  160. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/fontawesome.min.css +0 -9
  161. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/solid.min.css +0 -6
  162. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  163. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  164. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.css +0 -1
  165. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.js +0 -2
  166. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.css +0 -661
  167. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.js +0 -6
  168. solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/split/split.min.js +0 -3
  169. solverforge-0.4.0/python/solverforge/__init__.py +0 -47
  170. solverforge-0.4.0/python/solverforge/_native.pyi +0 -20
  171. solverforge-0.4.0/python/solverforge/decorators.py +0 -97
  172. solverforge-0.4.0/python/solverforge/fields.py +0 -61
  173. solverforge-0.4.0/python/solverforge/joiner.py +0 -28
  174. solverforge-0.4.0/python/solverforge/model.py +0 -132
  175. solverforge-0.4.0/src/config.rs +0 -58
  176. solverforge-0.4.0/src/constraints/evaluate.rs +0 -80
  177. solverforge-0.4.0/src/error.rs +0 -9
  178. solverforge-0.4.0/src/manager/events.rs +0 -154
  179. solverforge-0.4.0/src/manager/mod.rs +0 -4
  180. solverforge-0.4.0/src/runtime/distance.rs +0 -17
  181. solverforge-0.4.0/src/runtime/dynamic_scalar_search.rs +0 -4169
  182. solverforge-0.4.0/src/runtime/list_slots.rs +0 -28
  183. solverforge-0.4.0/src/runtime/mod.rs +0 -30
  184. solverforge-0.4.0/src/runtime/scalar_slots.rs +0 -29
  185. solverforge-0.4.0/src/runtime/static_fns.rs +0 -21
  186. solverforge-0.4.0/src/runtime/thread_local.rs +0 -21
  187. solverforge-0.4.0/src/schema/parse.rs +0 -119
  188. solverforge-0.4.0/src/schema/types.rs +0 -44
  189. solverforge-0.4.0/src/schema/validate.rs +0 -20
  190. solverforge-0.4.0/src/solver/solvable.rs +0 -55
  191. solverforge-0.4.0/src/state/entity_table.rs +0 -49
  192. solverforge-0.4.0/src/state/marshal.rs +0 -155
  193. solverforge-0.4.0/src/state/solution.rs +0 -233
  194. solverforge-0.4.0/src/state/variables.rs +0 -22
  195. solverforge-0.4.0/tests/python/test_constraints.py +0 -341
  196. solverforge-0.4.0/tests/python/test_decorators.py +0 -53
  197. solverforge-0.4.0/tests/python/test_list_solving.py +0 -336
  198. solverforge-0.4.0/tests/python/test_manager.py +0 -47
  199. solverforge-0.4.0/tests/python/test_scalar_solving.py +0 -851
  200. solverforge-0.4.0/tests/python/test_tracebacks.py +0 -40
  201. solverforge-0.4.0/tests/rust/constraint_set.rs +0 -33
  202. solverforge-0.4.0/tests/rust/runtime_slots.rs +0 -92
  203. solverforge-0.4.0/tests/rust/state_clone.rs +0 -97
  204. {solverforge-0.4.0 → solverforge-0.6.0}/.gitignore +0 -0
  205. {solverforge-0.4.0 → solverforge-0.6.0}/.pre-commit-config.yaml +0 -0
  206. {solverforge-0.4.0 → solverforge-0.6.0}/.python-version +0 -0
  207. {solverforge-0.4.0 → solverforge-0.6.0}/LICENSE +0 -0
  208. {solverforge-0.4.0 → solverforge-0.6.0}/examples/list_tsp.py +0 -0
  209. {solverforge-0.4.0 → solverforge-0.6.0}/examples/mixed_job_shop.py +0 -0
  210. {solverforge-0.4.0 → solverforge-0.6.0}/examples/nqueens.py +0 -0
  211. {solverforge-0.4.0 → solverforge-0.6.0}/examples/shift_scheduling.py +0 -0
  212. {solverforge-0.4.0/examples/solverforge_hospital → solverforge-0.6.0/examples/solverforge_deliveries}/src/api/sse.py +0 -0
  213. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/__init__.py +0 -0
  214. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/__main__.py +0 -0
  215. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/__init__.py +0 -0
  216. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/__init__.py +0 -0
  217. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/mod.py +0 -0
  218. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/__init__.py +0 -0
  219. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/assigned_shift.py +0 -0
  220. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/balance_assignments.py +0 -0
  221. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/desired_day.py +0 -0
  222. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/minimum_rest.py +0 -0
  223. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/mod.py +0 -0
  224. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/one_shift_per_day.py +0 -0
  225. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/overlapping_shift.py +0 -0
  226. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/required_skill.py +0 -0
  227. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/unavailable_employee.py +0 -0
  228. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/undesired_day.py +0 -0
  229. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/__init__.py +0 -0
  230. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/LARGE.json +0 -0
  231. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/__init__.py +0 -0
  232. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/availability.py +0 -0
  233. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/cohorts.py +0 -0
  234. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/coverage.py +0 -0
  235. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/demand.py +0 -0
  236. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/employees.py +0 -0
  237. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/entrypoints.py +0 -0
  238. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/large.py +0 -0
  239. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/preferences.py +0 -0
  240. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/shifts.py +0 -0
  241. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/skills.py +0 -0
  242. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/time_utils.py +0 -0
  243. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/validation.py +0 -0
  244. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/vocabulary.py +0 -0
  245. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/witness.py +0 -0
  246. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/mod.py +0 -0
  247. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/__init__.py +0 -0
  248. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/care_hub.py +0 -0
  249. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/employee.py +0 -0
  250. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/mod.py +0 -0
  251. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/lib.py +0 -0
  252. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/main.py +0 -0
  253. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/__init__.py +0 -0
  254. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/mod.py +0 -0
  255. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/__init__.py +0 -0
  256. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/mod.py +0 -0
  257. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/main.mjs +0 -0
  258. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/analysis-modal.mjs +0 -0
  259. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/datetime.mjs +0 -0
  260. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/employee-view.mjs +0 -0
  261. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/grouping.mjs +0 -0
  262. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/identity.mjs +0 -0
  263. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/location-view.mjs +0 -0
  264. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/presentation.mjs +0 -0
  265. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/rail-renderer.mjs +0 -0
  266. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/api-guide.mjs +0 -0
  267. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/app-shell.mjs +0 -0
  268. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/app-state.mjs +0 -0
  269. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/config-loader.mjs +0 -0
  270. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/data-panel.mjs +0 -0
  271. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/solver-controller.mjs +0 -0
  272. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/views/registry.mjs +0 -0
  273. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/generated/ui-model.json +0 -0
  274. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/index.html +0 -0
  275. {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/sf-config.json +0 -0
  276. {solverforge-0.4.0 → solverforge-0.6.0}/examples/vrp_owner_hooks.py +0 -0
  277. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/console.py +0 -0
  278. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/errors.py +0 -0
  279. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/events.py +0 -0
  280. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/py.typed +0 -0
  281. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/score.py +0 -0
  282. {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/typing.py +0 -0
  283. {solverforge-0.4.0 → solverforge-0.6.0}/rust-toolchain.toml +0 -0
  284. {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/call.rs +0 -0
  285. {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/mod.rs +0 -0
  286. {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/registry.rs +0 -0
  287. {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/threading.rs +0 -0
  288. {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/incremental.rs +0 -0
  289. {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/matches.rs +0 -0
  290. {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/stream_plan.rs +0 -0
  291. {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/extractor.rs +0 -0
  292. {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/mod.rs +0 -0
  293. {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/variable.rs +0 -0
  294. {solverforge-0.4.0 → solverforge-0.6.0}/src/intern.rs +0 -0
  295. {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/entity.rs +0 -0
  296. {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/list.rs +0 -0
  297. {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/mod.rs +0 -0
  298. {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/solution.rs +0 -0
  299. {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/build.rs +0 -0
  300. {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/python.rs +0 -0
  301. {solverforge-0.4.0 → solverforge-0.6.0}/src/score.rs +0 -0
  302. {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/mod.rs +0 -0
  303. {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/progress.rs +0 -0
  304. {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/result.rs +0 -0
  305. {solverforge-0.4.0 → solverforge-0.6.0}/src/state/clone.rs +0 -0
  306. {solverforge-0.4.0 → solverforge-0.6.0}/src/value.rs +0 -0
  307. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_mixed_solving.py +0 -0
  308. {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_threading.py +0 -0
  309. {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/manager.rs +0 -0
  310. {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/score.rs +0 -0
  311. {solverforge-0.4.0 → solverforge-0.6.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*.*.*"
@@ -23,9 +14,18 @@ env:
23
14
  RUST_VERSION: "1.95.0"
24
15
 
25
16
  jobs:
17
+ forgejo-release-guard:
18
+ name: Forgejo release guard
19
+ if: github.server_url != 'https://github.com'
20
+ runs-on: rust
21
+ steps:
22
+ - name: Skip publish-only release workflow
23
+ run: echo "Release publishing runs only on GitHub; Forgejo tag CI is intentionally a no-op."
24
+
26
25
  sdist:
27
26
  name: source distribution
28
- runs-on: ubuntu-latest
27
+ if: github.server_url == 'https://github.com'
28
+ runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'rust' }}
29
29
  steps:
30
30
  - name: Checkout solverforge-py
31
31
  uses: actions/checkout@v6
@@ -55,7 +55,8 @@ jobs:
55
55
 
56
56
  wheels:
57
57
  name: wheel ${{ matrix.os }} ${{ matrix.target }}
58
- runs-on: ${{ matrix.os }}
58
+ if: github.server_url == 'https://github.com'
59
+ runs-on: ${{ github.server_url == 'https://github.com' && matrix.os || 'rust' }}
59
60
  strategy:
60
61
  fail-fast: false
61
62
  matrix:
@@ -101,7 +102,8 @@ jobs:
101
102
 
102
103
  verify:
103
104
  name: verify artifacts
104
- runs-on: ubuntu-latest
105
+ if: github.server_url == 'https://github.com'
106
+ runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'rust' }}
105
107
  needs: [sdist, wheels]
106
108
  steps:
107
109
  - name: Checkout solverforge-py
@@ -138,9 +140,13 @@ jobs:
138
140
 
139
141
  publish-testpypi:
140
142
  name: publish to TestPyPI
141
- runs-on: ubuntu-latest
143
+ runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'rust' }}
142
144
  needs: verify
143
- if: github.event_name == 'workflow_dispatch' && github.event.inputs.repository == 'testpypi'
145
+ if: >-
146
+ always() &&
147
+ needs.verify.result == 'success' &&
148
+ github.server_url == 'https://github.com' &&
149
+ github.event_name == 'workflow_dispatch'
144
150
  environment: testpypi
145
151
  permissions:
146
152
  contents: read
@@ -159,11 +165,14 @@ jobs:
159
165
 
160
166
  publish-pypi:
161
167
  name: publish to PyPI
162
- runs-on: ubuntu-latest
168
+ runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'rust' }}
163
169
  needs: verify
164
170
  if: >-
165
- (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
166
- (github.event_name == 'workflow_dispatch' && github.event.inputs.repository == 'pypi')
171
+ always() &&
172
+ needs.verify.result == 'success' &&
173
+ github.server_url == 'https://github.com' &&
174
+ github.event_name == 'push' &&
175
+ startsWith(github.ref, 'refs/tags/v')
167
176
  environment: pypi
168
177
  permissions:
169
178
  contents: read
@@ -187,8 +196,6 @@ jobs:
187
196
 
188
197
  expected = f"v{version}"
189
198
  actual = os.environ["GITHUB_REF_NAME"]
190
- if os.environ["GITHUB_EVENT_NAME"] == "workflow_dispatch":
191
- raise SystemExit(0)
192
199
  if actual != expected:
193
200
  raise SystemExit(f"tag {actual} does not match package version {expected}")
194
201
  PY
@@ -0,0 +1,153 @@
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
+ One compiled schema owns one immutable runtime plan: parsed schema, descriptor,
77
+ upstream `RuntimeModel`, assignment bindings, constraints, and candidate metrics.
78
+ Direct solves, retained jobs, snapshots, clones, and resumes must use that same
79
+ plan; do not recreate wrapper-local phases, selector trees, move types, TLS slot
80
+ state, or fallback construction paths. Schema caching is allowed only for
81
+ structurally stable, capture-free callback state; stateful callbacks compile per
82
+ invocation.
83
+
84
+ Python callbacks are the only constraint authoring surface. Callback exceptions
85
+ must preserve actionable Python tracebacks. Callback solution views must expose
86
+ ordinary solution-level lookup context while projecting entity/fact collections
87
+ from Rust-owned state. Callback code may be called many times and from multiple
88
+ worker threads on CPython 3.14 free-threaded, so treat solution-level lookup
89
+ context as immutable during a solve.
90
+
91
+ `@candidate_metric` callbacks are the Python surface for named sorted or
92
+ probabilistic selector metrics. Register them through
93
+ `@planning_solution(..., candidate_metrics=[...])`; they receive the callback
94
+ solution view plus a canonical candidate identity and must return finite numeric
95
+ values. `selection_metric` is valid only with `sorted` or `probabilistic`
96
+ selection order, and probabilistic weights must be non-negative.
97
+
98
+ Ordinary dynamic scalar construction supports `first_fit` and
99
+ `cheapest_insertion`. Assignment-group construction also supports the decreasing,
100
+ weakest-fit, and strongest-fit scalar variants when their declared `entity_order`
101
+ and `value_order` capabilities satisfy the upstream compiler. Dynamic list
102
+ construction supports round-robin, cheapest/regret insertion, Clarke-Wright, and
103
+ K-opt; route-aware variants require their explicit savings or route metadata.
104
+
105
+ Candidate traces are bounded, opt-in retained diagnostics. Keep them out of
106
+ synchronous `Solver.solve`, ordinary statuses, and events; expose them only
107
+ through the atomic `SolverManager.telemetry_detail` payload. Qualified traces
108
+ require an explicit per-job `QualifiedCandidateTraceProvenance` with five
109
+ lowercase SHA-256 digests and a non-blank external producer. Never infer those
110
+ values from a solution, environment, callback, or file, and never accept
111
+ qualified provenance through serializable `SolverConfig`.
112
+
113
+ Do not fake unsupported behavior. Top-level `ConstraintFactory.join`,
114
+ `group_by`, `if_exists`, `if_not_exists`, and `flattened` remain explicit
115
+ unsupported methods until public bridge support exists for those top-level
116
+ semantics. Rust-only custom search and partitioner registration cannot be
117
+ claimed as Python-bindable without a public upstream seam.
118
+
119
+ ## Release Responsibilities
120
+
121
+ `pyproject.toml` owns PyPI metadata, version, Python requirement, optional
122
+ example dependencies, project URLs, classifiers, and maturin module settings.
123
+ `Cargo.toml` owns native crate metadata and the SolverForge Rust dependency
124
+ base; the package version must match `pyproject.toml`. `Cargo.lock` locks
125
+ reproducible Rust builds. The current release line is package/crate `0.6.0` on
126
+ the six SolverForge `0.18.0` registry crates and `solverforge-ui` `0.7.0`;
127
+ `make release-base-check` must stay green. The `Makefile` owns local release targets,
128
+ dependency-base checks, distribution builds, artifact validation, browser system
129
+ dependency setup, and `pre-release`. `.github/workflows/ci.yml` validates source
130
+ checkouts on GitHub and Forgejo, installs Playwright system dependencies on
131
+ Linux, and retries network toolchain bootstraps for transient runner DNS misses.
132
+ `.github/workflows/release.yml` builds sdists/wheels, verifies release
133
+ artifacts, publishes to TestPyPI only from manual workflow dispatch, and
134
+ publishes to PyPI automatically from a matching `v*.*.*` tag.
135
+ `scripts/verify_release_artifacts.py` checks deterministic artifact
136
+ metadata/content, and
137
+ `tests/python/test_release_metadata.py` guards release metadata drift.
138
+
139
+ ## Commit & Pull Request Guidelines
140
+
141
+ The history uses concise Conventional Commit-style subjects such as
142
+ `fix(runtime): preserve scalar snapshots` or `test(manager): cover retained jobs`.
143
+ Pull requests should include the motivation, user-visible behavior, tests run,
144
+ and any linked issue. Include screenshots or short recordings for changes under
145
+ `examples/solverforge_hospital/static/` or
146
+ `examples/solverforge_deliveries/static/`.
147
+
148
+ ## Agent-Specific Instructions
149
+
150
+ Keep changes scoped to the requested surface. Do not rewrite runtime, callback,
151
+ manager, or API payload paths for a simple documentation, UI, naming, or wiring
152
+ task unless live evidence proves that path is the failing layer. Verify assumptions
153
+ from the repo before changing critical integration code.
@@ -0,0 +1,61 @@
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.6.0](///compare/v0.5.0...v0.6.0) (2026-07-13)
6
+
7
+
8
+ ### Features
9
+
10
+ * **manager:** retain qualified solve diagnostics c6445ec
11
+ * **model:** declare explicit runtime metadata ad41f94
12
+
13
+ ## [0.5.0](https://github.com/SolverForge/solverforge-py/compare/v0.4.1...v0.5.0) (2026-07-03)
14
+
15
+
16
+ ### Features
17
+
18
+ * **examples:** add deliveries Python app 0179084
19
+ * **model:** carry dynamic route and shadow hooks 83a8d41
20
+ * **runtime:** bind Python list route hooks fd51788
21
+ * **runtime:** broaden dynamic Python planning surface f04eefa
22
+ * **ui:** embed shared frontend assets ab30697
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **ci:** bootstrap Forgejo toolchains in workflow 8e5f791
28
+ * **ci:** install Playwright system dependencies b249fd1
29
+ * **ci:** retry toolchain bootstrap downloads cd60f76
30
+ * **ci:** run workflow from checkout root 8733fc3
31
+ * **ci:** select Forgejo runner labels 56ff4fc
32
+ * **deliveries:** recommend assigned-route insertions d59daea
33
+ * **examples:** report snapshot score in payloads 0bfcaa0
34
+ * **examples:** report solution scores in events bdcddd8
35
+ * **model:** validate scalar group names cfa2070
36
+ * **runtime:** align dynamic construction with core semantics 7cacda0
37
+ * **runtime:** cap first-fit required construction candidates 3666c20
38
+ * **runtime:** resolve dynamic slots against descriptors a2544be
39
+ * **runtime:** reuse required assignment construction streams 0caf06d
40
+ * **runtime:** use direct cursor for first-fit assignments 769a081
41
+ * **scoring:** return true shadow update deltas 88dc500
42
+ * **state:** preserve callback root fields 0aacef5
43
+
44
+
45
+ ### Tests
46
+
47
+ * **examples:** stabilize hospital browser smoke f11efd6
48
+ * **examples:** stub map tiles in browser smoke d69ca3e
49
+
50
+
51
+ ### Documentation and release
52
+
53
+ * **docs:** remove standalone docs surface b1c6e1f
54
+ * **release:** cut 0.5.0 metadata 4728014
55
+
56
+ ## [0.4.1](https://github.com/SolverForge/solverforge-py/compare/v0.4.0...v0.4.1) (2026-06-02)
57
+
58
+
59
+ ### Bug Fixes
60
+
61
+ * **deps:** resolve SolverForge crates from crates.io 73bfe4a