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.
- solverforge-0.6.0/.github/workflows/ci.yml +69 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/.github/workflows/release.yml +27 -20
- solverforge-0.6.0/AGENTS.md +153 -0
- solverforge-0.6.0/CHANGELOG.md +61 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/Cargo.lock +78 -248
- solverforge-0.6.0/Cargo.toml +49 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/Makefile +72 -16
- solverforge-0.6.0/PKG-INFO +416 -0
- solverforge-0.6.0/README.md +384 -0
- solverforge-0.6.0/WIREFRAME.md +456 -0
- solverforge-0.6.0/examples/solverforge_deliveries/README.md +90 -0
- solverforge-0.6.0/examples/solverforge_deliveries/__init__.py +23 -0
- solverforge-0.6.0/examples/solverforge_deliveries/__main__.py +32 -0
- solverforge-0.6.0/examples/solverforge_deliveries/solver.toml +51 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/__init__.py +1 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/api/__init__.py +1 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/api/dto.py +233 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/api/mod.py +3 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/api/routes.py +239 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/constraints/__init__.py +5 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/constraints/mod.py +47 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/data/__init__.py +5 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/__init__.py +5 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/entrypoints.py +149 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/data/data_seed/locations.json +1472 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/data/mod.py +1 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/__init__.py +33 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/delivery.py +32 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/metrics.py +493 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/mod.py +1 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/plan.py +126 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/domain/vehicle.py +112 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/lib.py +34 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/main.py +22 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/solver/__init__.py +5 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/solver/mod.py +1 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/__init__.py +196 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/mod.py +7 -0
- solverforge-0.6.0/examples/solverforge_deliveries/src/solver/service/payload.py +86 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/main.mjs +287 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/core.mjs +57 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/formatters.mjs +53 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/preview.mjs +154 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/models/timeline.mjs +94 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/models.mjs +8 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/api-guide.mjs +29 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/components.mjs +44 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/data-tables.mjs +98 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/layout.mjs +123 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/lifecycle.mjs +23 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/modals.mjs +63 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app/ui/overview.mjs +172 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app.css +196 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/app.js +3 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/generated/ui-model.json +25 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/index.html +22 -0
- solverforge-0.6.0/examples/solverforge_deliveries/static/sf-config.json +4 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/README.md +35 -12
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/solver.toml +2 -2
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/dto.py +47 -9
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/routes.py +24 -4
- solverforge-0.6.0/examples/solverforge_hospital/src/api/sse.py +42 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/plan.py +52 -7
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/payload.py +18 -4
- {solverforge-0.4.0 → solverforge-0.6.0}/pyproject.toml +1 -1
- solverforge-0.6.0/python/solverforge/__init__.py +88 -0
- solverforge-0.6.0/python/solverforge/_native.pyi +72 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/config.py +27 -3
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/constraints.py +252 -8
- solverforge-0.6.0/python/solverforge/decorators.py +234 -0
- solverforge-0.6.0/python/solverforge/fields.py +494 -0
- solverforge-0.6.0/python/solverforge/groups.py +167 -0
- solverforge-0.6.0/python/solverforge/joiner.py +39 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/manager.py +31 -5
- solverforge-0.6.0/python/solverforge/model.py +326 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/solver.py +6 -4
- solverforge-0.6.0/python/solverforge/ui.py +29 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/scripts/verify_release_artifacts.py +48 -13
- {solverforge-0.4.0 → solverforge-0.6.0}/scripts/verify_solverforge_release_base.py +11 -26
- {solverforge-0.4.0 → solverforge-0.6.0}/src/bindings.rs +8 -0
- solverforge-0.6.0/src/config.rs +113 -0
- solverforge-0.6.0/src/constraints/compiled.rs +322 -0
- solverforge-0.6.0/src/constraints/evaluate.rs +159 -0
- solverforge-0.6.0/src/constraints/list_precedence.rs +935 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/mod.rs +2 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/state.rs +1280 -249
- solverforge-0.6.0/src/error.rs +44 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/lib.rs +1 -0
- solverforge-0.6.0/src/manager/candidate_trace.rs +388 -0
- solverforge-0.6.0/src/manager/events.rs +564 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/manager/jobs.rs +107 -20
- solverforge-0.6.0/src/manager/mod.rs +7 -0
- solverforge-0.6.0/src/manager/provenance.rs +205 -0
- solverforge-0.6.0/src/runtime/candidate_metric.rs +119 -0
- solverforge-0.6.0/src/runtime/dynamic_assignment_group.rs +471 -0
- solverforge-0.6.0/src/runtime/dynamic_provider.rs +291 -0
- solverforge-0.6.0/src/runtime/list_slots.rs +798 -0
- solverforge-0.6.0/src/runtime/mod.rs +46 -0
- solverforge-0.6.0/src/runtime/scalar_slots.rs +337 -0
- solverforge-0.6.0/src/schema/compiled.rs +43 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/mod.rs +2 -0
- solverforge-0.6.0/src/schema/parse.rs +760 -0
- solverforge-0.6.0/src/schema/runtime_plan.rs +71 -0
- solverforge-0.6.0/src/schema/types.rs +266 -0
- solverforge-0.6.0/src/schema/validate.rs +118 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/api.rs +32 -45
- {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/console.rs +14 -15
- solverforge-0.6.0/src/solver/solvable.rs +53 -0
- solverforge-0.6.0/src/state/callback_view.rs +616 -0
- solverforge-0.6.0/src/state/entity_table.rs +143 -0
- solverforge-0.6.0/src/state/marshal.rs +1195 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/state/mod.rs +1 -0
- solverforge-0.6.0/src/state/solution.rs +844 -0
- solverforge-0.6.0/src/state/variables.rs +18 -0
- solverforge-0.6.0/src/ui.rs +194 -0
- solverforge-0.6.0/tests/python/test_candidate_trace_provenance.py +174 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_config.py +37 -8
- solverforge-0.6.0/tests/python/test_constraints.py +1440 -0
- solverforge-0.6.0/tests/python/test_decorators.py +606 -0
- solverforge-0.6.0/tests/python/test_deliveries_example.py +380 -0
- solverforge-0.6.0/tests/python/test_deliveries_frontend_app.py +289 -0
- solverforge-0.6.0/tests/python/test_examples_import_surface.py +63 -0
- solverforge-0.6.0/tests/python/test_examples_playwright.py +296 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_hospital_example.py +33 -3
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_hospital_frontend_app.py +147 -9
- solverforge-0.6.0/tests/python/test_list_solving.py +2089 -0
- solverforge-0.6.0/tests/python/test_manager.py +372 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_release_metadata.py +81 -10
- solverforge-0.6.0/tests/python/test_scalar_solving.py +3275 -0
- solverforge-0.6.0/tests/python/test_tracebacks.py +185 -0
- solverforge-0.6.0/tests/python/test_ui_assets.py +125 -0
- solverforge-0.6.0/tests/rust/constraint_set.rs +45 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/descriptor.rs +18 -6
- solverforge-0.6.0/tests/rust/runtime_slots.rs +226 -0
- solverforge-0.6.0/tests/rust/state_clone.rs +306 -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/__init__.py +0 -47
- solverforge-0.4.0/python/solverforge/_native.pyi +0 -20
- solverforge-0.4.0/python/solverforge/decorators.py +0 -97
- solverforge-0.4.0/python/solverforge/fields.py +0 -61
- solverforge-0.4.0/python/solverforge/joiner.py +0 -28
- solverforge-0.4.0/python/solverforge/model.py +0 -132
- solverforge-0.4.0/src/config.rs +0 -58
- solverforge-0.4.0/src/constraints/evaluate.rs +0 -80
- solverforge-0.4.0/src/error.rs +0 -9
- solverforge-0.4.0/src/manager/events.rs +0 -154
- solverforge-0.4.0/src/manager/mod.rs +0 -4
- solverforge-0.4.0/src/runtime/distance.rs +0 -17
- solverforge-0.4.0/src/runtime/dynamic_scalar_search.rs +0 -4169
- solverforge-0.4.0/src/runtime/list_slots.rs +0 -28
- solverforge-0.4.0/src/runtime/mod.rs +0 -30
- solverforge-0.4.0/src/runtime/scalar_slots.rs +0 -29
- solverforge-0.4.0/src/runtime/static_fns.rs +0 -21
- solverforge-0.4.0/src/runtime/thread_local.rs +0 -21
- 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/solver/solvable.rs +0 -55
- solverforge-0.4.0/src/state/entity_table.rs +0 -49
- solverforge-0.4.0/src/state/marshal.rs +0 -155
- solverforge-0.4.0/src/state/solution.rs +0 -233
- solverforge-0.4.0/src/state/variables.rs +0 -22
- solverforge-0.4.0/tests/python/test_constraints.py +0 -341
- solverforge-0.4.0/tests/python/test_decorators.py +0 -53
- solverforge-0.4.0/tests/python/test_list_solving.py +0 -336
- solverforge-0.4.0/tests/python/test_manager.py +0 -47
- solverforge-0.4.0/tests/python/test_scalar_solving.py +0 -851
- solverforge-0.4.0/tests/python/test_tracebacks.py +0 -40
- solverforge-0.4.0/tests/rust/constraint_set.rs +0 -33
- solverforge-0.4.0/tests/rust/runtime_slots.rs +0 -92
- solverforge-0.4.0/tests/rust/state_clone.rs +0 -97
- {solverforge-0.4.0 → solverforge-0.6.0}/.gitignore +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/.pre-commit-config.yaml +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/.python-version +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/LICENSE +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/list_tsp.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/mixed_job_shop.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/nqueens.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/shift_scheduling.py +0 -0
- {solverforge-0.4.0/examples/solverforge_hospital → solverforge-0.6.0/examples/solverforge_deliveries}/src/api/sse.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/__main__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/api/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/assigned_shift.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/balance_assignments.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/desired_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/minimum_rest.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/one_shift_per_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/overlapping_shift.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/required_skill.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/unavailable_employee.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/constraints/undesired_day.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/LARGE.json +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/availability.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/cohorts.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/coverage.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/demand.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/employees.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/entrypoints.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/large.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/preferences.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/shifts.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/skills.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/time_utils.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/validation.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/vocabulary.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/data_seed/witness.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/data/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/care_hub.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/employee.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/domain/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/lib.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/main.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/__init__.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/src/solver/service/mod.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/main.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/analysis-modal.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/datetime.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/employee-view.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/grouping.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/identity.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/location-view.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/presentation.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/schedule/rail-renderer.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/api-guide.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/app-shell.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/app-state.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/config-loader.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/data-panel.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/shell/solver-controller.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/app/views/registry.mjs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/generated/ui-model.json +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/index.html +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/solverforge_hospital/static/sf-config.json +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/examples/vrp_owner_hooks.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/console.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/errors.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/events.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/py.typed +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/score.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/python/solverforge/typing.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/rust-toolchain.toml +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/call.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/registry.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/callbacks/threading.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/incremental.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/matches.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/constraints/stream_plan.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/extractor.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/descriptor/variable.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/intern.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/entity.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/list.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/proxy/solution.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/build.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/schema/python.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/score.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/mod.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/progress.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/solver/result.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/state/clone.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/src/value.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_mixed_solving.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/python/test_threading.py +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/manager.rs +0 -0
- {solverforge-0.4.0 → solverforge-0.6.0}/tests/rust/score.rs +0 -0
- {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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
(
|
|
166
|
-
|
|
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
|