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.
- solverforge-0.5.0/.github/workflows/ci.yml +69 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/.github/workflows/release.yml +11 -16
- solverforge-0.5.0/AGENTS.md +121 -0
- solverforge-0.5.0/CHANGELOG.md +53 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/Cargo.lock +78 -248
- solverforge-0.5.0/Cargo.toml +49 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/Makefile +61 -16
- solverforge-0.5.0/PKG-INFO +336 -0
- solverforge-0.5.0/README.md +304 -0
- solverforge-0.5.0/WIREFRAME.md +306 -0
- solverforge-0.5.0/examples/solverforge_deliveries/README.md +85 -0
- solverforge-0.5.0/examples/solverforge_deliveries/__init__.py +23 -0
- solverforge-0.5.0/examples/solverforge_deliveries/__main__.py +32 -0
- solverforge-0.5.0/examples/solverforge_deliveries/solver.toml +51 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/__init__.py +1 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/api/__init__.py +1 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/api/dto.py +215 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/api/mod.py +3 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/api/routes.py +239 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/constraints/__init__.py +5 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/constraints/mod.py +47 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/data/__init__.py +5 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/__init__.py +5 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/entrypoints.py +213 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/data/data_seed/locations.json +1472 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/data/mod.py +1 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/__init__.py +33 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/delivery.py +32 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/metrics.py +404 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/mod.py +1 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/plan.py +84 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/domain/vehicle.py +41 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/lib.py +34 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/main.py +22 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/solver/__init__.py +5 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/solver/mod.py +1 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/__init__.py +196 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/mod.py +7 -0
- solverforge-0.5.0/examples/solverforge_deliveries/src/solver/service/payload.py +86 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/main.mjs +287 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/core.mjs +57 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/formatters.mjs +53 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/preview.mjs +154 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/models/timeline.mjs +94 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/models.mjs +8 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/api-guide.mjs +29 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/components.mjs +44 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/data-tables.mjs +98 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/layout.mjs +123 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/lifecycle.mjs +23 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/modals.mjs +63 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app/ui/overview.mjs +172 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app.css +196 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/app.js +3 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/generated/ui-model.json +25 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/index.html +22 -0
- solverforge-0.5.0/examples/solverforge_deliveries/static/sf-config.json +4 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/README.md +26 -8
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/dto.py +29 -9
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/routes.py +24 -4
- solverforge-0.5.0/examples/solverforge_hospital/src/api/sse.py +42 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/payload.py +18 -4
- {solverforge-0.4.0 → solverforge-0.5.0}/pyproject.toml +1 -1
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/__init__.py +21 -4
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/_native.pyi +12 -2
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/constraints.py +220 -8
- solverforge-0.5.0/python/solverforge/decorators.py +146 -0
- solverforge-0.5.0/python/solverforge/fields.py +133 -0
- solverforge-0.5.0/python/solverforge/groups.py +99 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/model.py +38 -5
- solverforge-0.5.0/python/solverforge/ui.py +29 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/scripts/verify_release_artifacts.py +48 -13
- {solverforge-0.4.0 → solverforge-0.5.0}/scripts/verify_solverforge_release_base.py +11 -26
- {solverforge-0.4.0 → solverforge-0.5.0}/src/bindings.rs +2 -0
- solverforge-0.5.0/src/constraints/evaluate.rs +159 -0
- solverforge-0.5.0/src/constraints/list_precedence.rs +767 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/mod.rs +1 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/state.rs +884 -159
- {solverforge-0.4.0 → solverforge-0.5.0}/src/lib.rs +1 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/jobs.rs +13 -1
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/dynamic_scalar_search.rs +2335 -197
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/mod.rs +4 -2
- solverforge-0.5.0/src/schema/parse.rs +260 -0
- solverforge-0.5.0/src/schema/types.rs +112 -0
- solverforge-0.5.0/src/schema/validate.rs +38 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/api.rs +13 -4
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/solvable.rs +7 -2
- solverforge-0.5.0/src/state/callback_view.rs +294 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/state/entity_table.rs +3 -1
- solverforge-0.5.0/src/state/marshal.rs +349 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/state/mod.rs +1 -0
- solverforge-0.5.0/src/state/solution.rs +465 -0
- solverforge-0.5.0/src/ui.rs +194 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_constraints.py +298 -1
- solverforge-0.5.0/tests/python/test_deliveries_example.py +329 -0
- solverforge-0.5.0/tests/python/test_deliveries_frontend_app.py +255 -0
- solverforge-0.5.0/tests/python/test_examples_import_surface.py +63 -0
- solverforge-0.5.0/tests/python/test_examples_playwright.py +296 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_hospital_frontend_app.py +110 -7
- solverforge-0.5.0/tests/python/test_list_solving.py +1472 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_manager.py +36 -1
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_release_metadata.py +83 -10
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_scalar_solving.py +682 -3
- solverforge-0.5.0/tests/python/test_ui_assets.py +125 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/constraint_set.rs +5 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/descriptor.rs +6 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/runtime_slots.rs +20 -4
- solverforge-0.5.0/tests/rust/state_clone.rs +226 -0
- solverforge-0.4.0/.github/workflows/ci.yml +0 -46
- solverforge-0.4.0/AGENTS.md +0 -62
- solverforge-0.4.0/Cargo.toml +0 -51
- solverforge-0.4.0/PKG-INFO +0 -187
- solverforge-0.4.0/README.md +0 -155
- solverforge-0.4.0/WIREFRAME.md +0 -152
- solverforge-0.4.0/docs/callback-contract.md +0 -18
- solverforge-0.4.0/docs/dynamic-move-parity-plan.md +0 -203
- solverforge-0.4.0/docs/goal.md +0 -305
- solverforge-0.4.0/docs/non-goals.md +0 -9
- solverforge-0.4.0/docs/release.md +0 -90
- solverforge-0.4.0/docs/threading.md +0 -12
- solverforge-0.4.0/docs/upstream-contract.md +0 -33
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/jetbrains-mono.woff2 +0 -0
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/fonts/space-grotesk.woff2 +0 -0
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/img/ouroboros.svg +0 -60
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.css +0 -77
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/modules/sf-map.js +0 -165
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.css +0 -2490
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.js +0 -4012
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.0.6.5.mjs +0 -3987
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.css +0 -2490
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.js +0 -4012
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/sf.mjs +0 -3987
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/fontawesome.min.css +0 -9
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/css/solid.min.css +0 -6
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.css +0 -1
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/frappe-gantt/frappe-gantt.min.js +0 -2
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.css +0 -661
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/leaflet/leaflet.js +0 -6
- solverforge-0.4.0/examples/solverforge_hospital/static/sf/vendor/split/split.min.js +0 -3
- solverforge-0.4.0/python/solverforge/decorators.py +0 -97
- solverforge-0.4.0/python/solverforge/fields.py +0 -61
- solverforge-0.4.0/src/constraints/evaluate.rs +0 -80
- solverforge-0.4.0/src/schema/parse.rs +0 -119
- solverforge-0.4.0/src/schema/types.rs +0 -44
- solverforge-0.4.0/src/schema/validate.rs +0 -20
- solverforge-0.4.0/src/state/marshal.rs +0 -155
- solverforge-0.4.0/src/state/solution.rs +0 -233
- solverforge-0.4.0/tests/python/test_list_solving.py +0 -336
- solverforge-0.4.0/tests/rust/state_clone.rs +0 -97
- {solverforge-0.4.0 → solverforge-0.5.0}/.gitignore +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/.pre-commit-config.yaml +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/.python-version +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/LICENSE +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/list_tsp.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/mixed_job_shop.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/nqueens.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/shift_scheduling.py +0 -0
- {solverforge-0.4.0/examples/solverforge_hospital → solverforge-0.5.0/examples/solverforge_deliveries}/src/api/sse.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/__main__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/solver.toml +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/api/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/assigned_shift.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/balance_assignments.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/desired_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/minimum_rest.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/one_shift_per_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/overlapping_shift.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/required_skill.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/unavailable_employee.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/constraints/undesired_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/LARGE.json +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/availability.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/cohorts.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/coverage.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/demand.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/employees.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/entrypoints.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/large.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/preferences.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/shifts.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/skills.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/time_utils.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/validation.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/vocabulary.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/data_seed/witness.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/data/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/care_hub.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/employee.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/domain/plan.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/lib.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/main.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/src/solver/service/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/main.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/analysis-modal.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/datetime.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/employee-view.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/grouping.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/identity.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/location-view.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/presentation.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/schedule/rail-renderer.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/api-guide.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/app-shell.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/app-state.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/config-loader.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/data-panel.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/shell/solver-controller.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/app/views/registry.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/generated/ui-model.json +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/index.html +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/solverforge_hospital/static/sf-config.json +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/examples/vrp_owner_hooks.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/config.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/console.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/errors.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/events.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/joiner.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/manager.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/py.typed +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/score.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/solver.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/python/solverforge/typing.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/rust-toolchain.toml +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/call.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/registry.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/callbacks/threading.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/config.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/incremental.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/matches.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/constraints/stream_plan.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/extractor.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/descriptor/variable.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/error.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/intern.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/events.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/manager/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/entity.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/list.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/proxy/solution.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/distance.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/list_slots.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/scalar_slots.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/static_fns.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/runtime/thread_local.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/build.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/schema/python.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/score.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/console.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/progress.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/solver/result.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/state/clone.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/state/variables.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/src/value.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_config.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_decorators.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_hospital_example.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_mixed_solving.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_threading.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/python/test_tracebacks.py +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/manager.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.5.0}/tests/rust/score.rs +0 -0
- {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:
|
|
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
|
-
|
|
166
|
-
|
|
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
|